c# - 使用 Autofixture、Moq 和 XUnit 的类中的部分模拟方法

标签 c# unit-testing moq xunit autofixture

我只想模拟一个类的某些方法,并为其他方法调用真正的实现。

我有我的 sut 类测试,其中 Runner 类被注入(inject)到构造函数中。这个注入(inject)的类在构造函数中再次注入(inject)了另一个类 RunnerParam。

该代码是我尝试仅掌握基础知识的实际类(class)的简化案例。

[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);
    }
}

我想模拟并为 Runner 类中的方法 Run 提供模拟值,但要使用方法 RunImplementation 的真实实现。

我希望看到 result2 500,但它是 0,这意味着该方法未被视为模型。在我看来这是正确的,但 Moq 调用库等于 true,因此应该采用真正的实现,但事实并非如此。

我在这里错过了什么?

最佳答案

在所示的简化示例中,Test 仅依赖于 IRunner

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

因此,如果打算单独测试 Test 类,那么这就是所有需要模拟的内容。

//...

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

//...

如果 Runner 类也被隔离测试,则需要模拟的 RunnerParam 来满足其依赖性。

然而,它应该依赖于抽象(接口(interface))而不是具体(实现)。

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

这简化了原始问题中描述的隔离测试

I want to mock and give a mocked value to the method Run in the class Runner, but to use the real implementation of the method 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);

关于c# - 使用 Autofixture、Moq 和 XUnit 的类中的部分模拟方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58507361/

相关文章:

c# - C# 代码中的 Excel 引用问题

c# - .Net 4 - 在程序集中包含自定义信息

unit-testing - react 堆项目 : wait while broadcaster finish

c# - 如何模拟抽象基类

c# - OSX 上的 Mono WCF 问题

C# - 覆盖事件处理程序 - 添加参数

java - Maven - 运行集成和单元测试

java - Android 测试类在 Eclipse 中编译失败,出现 "bound mismatch"错误

c# - 访问方法 'System.Web.Http.HttpConfiguration.DefaultFormatters()' 失败

c# - 如何在 MOQ 中使用 new 关键字模拟在方法内部创建的类对象