簡體   English   中英

class 中使用 Autofixture、Moq 和 XUnit 的部分模擬方法

[英]Partial mock methods in a class using Autofixture, Moq and XUnit

我只想模擬 class 的一些方法,並為其他方法調用真正的實現。

我有我的 sut class 測試,其中 Runner class 被注入到構造函數中。 這個注入的 class 在構造函數中再次注入了其他 class RunnerParam。

該代碼是我嘗試僅具有基礎知識的真實課程的簡化案例。

[Fact]
public void Test()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());

    var paramMock = fixture.Freeze<Mock<IRunnerParam>>();
    paramMock.Setup(x => x.Multiplicator()).Returns(2);

    var classMock = fixture.Freeze<Mock<IRunner>>();
    classMock.Setup(x => x.Run()).Returns(5);

    var test = fixture.Create<Test>();

    var result = test.StartRunning();  // should be 5
    var result2 = test.StartRunningImplementation(5); // should be 500
}

支持成員

public interface IRunnerParam
{
    int Multiplicator();
}

public class RunnerParam : IRunnerParam
{
    public virtual int Multiplicator()
    {
        return 20;
    }
}

public interface IRunner
{
    int Run();
    int RunImplementation(int param);
}

public class Runner : IRunner
{
    protected virtual RunnerParam MultiParam { get; set; }
    public Runner(RunnerParam multiParam)
    {
        MultiParam = multiParam;
    }

    public virtual int Run()
    {
        return 10;
    }

    public int RunImplementation(int param)
    {
        return 10 * MultiParam.Multiplicator() * param * Run();
    }
}

public class Test
{
    private readonly IRunner _runner;
    public Test(IRunner runner)
    {
        _runner = runner;
    }

    public int StartRunning()
    {
        return _runner.Run();
    }

    public int StartRunningImplementation(int param)
    {
        return _runner.RunImplementation(param);
    }
}

我想模擬並給 class Runner 中的方法 Run 一個模擬值,但要使用方法 RunImplementation 的真正實現。

我希望看到 result2 500,但它是 0,這意味着該方法不被視為模擬。 在我看來,這是正確的,但 Moq callbase 等於 true,所以應該采用真正的實現,但事實並非如此。

我在這里想念什么?

在所示的簡化示例中, Test僅依賴於IRunner

private readonly IRunner _runner;
public Test(IRunner runner)
{
    _runner = runner;
}

因此,如果打算單獨測試Test class,那么這就是所有需要嘲笑的東西。

//...

var classMock = fixture.Freeze<Mock<IRunner>>();
classMock.Setup(x => x.Run()).Returns(5);
classMock.Setup(x => x.RunImplementation(It.IsAny<int>())).Returns(500);

//...

如果要單獨測試Runner class,則需要一個模擬的RunnerParam來滿足其依賴關系。

然而,它應該依賴於抽象(接口)而不是具體(實現)。

protected virtual IRunnerParam MultiParam { get; set; }
public Runner(IRunnerParam multiParam) {
    MultiParam = multiParam;
}

這簡化了原始問題中描述的隔離測試

我想模擬並給 class Runner 中的方法 Run 一個模擬值,但要使用方法 RunImplementation 的真正實現。

//Arrange
var fixture = new Fixture().Customize(new AutoMoqCustomization());

var runnerParam = fixture.Freeze<Mock<IRunnerParam>>()
    .Setup(_ => _.Multiplicator())
    .Returns(2);

var subjectMock = fixture.Freeze<Mock<Runner>>();
subjectMock.CallBase = true;
subjectMock.Setup(_ => _.Run()).Returns(5);

int expected = 500;
Runner sut = subjectMock.Object;

//Act
var actual = sut.RunImplementation(5); // should be 500

//Assert
actual.Should().Be(expected);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM