class 中使用 Autofixture、Moq 和 XUnit 的部分模拟方法
Partial mock methods in a class using Autofixture, Moq and XUnit
我只想模拟 class 的某些方法,并为其他方法调用真正的实现。
我有我的 sut class 测试 运行ner class 被注入到构造函数中。这个注入的 class 在构造函数中再次注入了其他 class 运行nerParam。
代码是我的真实 classes 的简化案例,试图只掌握基础知识。
[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 运行 中的方法 运行 一个模拟值,但是要使用方法 运行 的真实实现实施。
我希望看到 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;
}
这简化了原始问题中描述的隔离测试
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);
我只想模拟 class 的某些方法,并为其他方法调用真正的实现。
我有我的 sut class 测试 运行ner class 被注入到构造函数中。这个注入的 class 在构造函数中再次注入了其他 class 运行nerParam。
代码是我的真实 classes 的简化案例,试图只掌握基础知识。
[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 运行 中的方法 运行 一个模拟值,但是要使用方法 运行 的真实实现实施。
我希望看到 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;
}
这简化了原始问题中描述的隔离测试
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);