想知道是否有办法使用AutoFixture和NSubstitute在具体类上模拟虚拟方法。我已经能够轻松地使用Moq,这可以在这里看到:
public class SomeConcreteClass
{
public string MethodA()
{
return MethodB();
}
public virtual string MethodB()
{
return "AAA";
}
}
[TestFixture]
public class SomeConcreteClassTests
{
private IFixture _fixture;
private SomeConcreteClass _someConcreteClass;
[SetUp]
protected void Setup()
{
_fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var someConcreteClassMock = _fixture.Create<Mock<SomeConcreteClass>>();
_someConcreteClass = someConcreteClassMock.Object;
someConcreteClassMock.CallBase = true;
}
[Test]
public void SomeScenario()
{
Mock.Get(_someConcreteClass).Setup(m => m.MethodB()).Returns("BBB");
var actual = _someConcreteClass.MethodA();
actual.ShouldBe("BBB");
}
}
答案 0 :(得分:2)
如果您使用AutoFixture对Parametrised Tests的支持,最好能够实现这一点,此处使用xUnit.net进行说明(但是,IIRC,对NUnit有类似的支持):
[Theory, AutoNSubstituteData]
public void ImplicitSubtituteViaAttribute([Substitute]SomeConcreteClass scc)
{
scc.MethodB().Returns("BBB");
var actual = scc.MethodB();
Assert.Equal("BBB", actual);
}
使用[Substitute]
属性可以明确告诉AutoFixture,虽然你要求一个具体的类,它应该通过NSubstitute创建它,以便你可以覆盖它可能拥有的任何虚拟成员。
AutoNSubstituteData
的定义如下:
public class AutoNSubstituteDataAttribute : AutoDataAttribute
{
public AutoNSubstituteDataAttribute() :
base(() => new Fixture().Customize(new AutoNSubstituteCustomization()))
{
}
}
AutoDataAttribute
来自AutoFixture.Xunit2,但如果您更喜欢NUnit而不是xUnit.net,那么您应该能够使用AutoFixture.NUnit3。
否则,我不确定您是否可以获得与AutoFixture.AutoMoq完全相同的结果。在这个退化的例子中,你可以这样做:
[Fact]
public void ImperativeWorkaround()
{
var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
fixture.Register(() => Substitute.For<SomeConcreteClass>());
var scc = fixture.Create<SomeConcreteClass>();
scc.MethodB().Returns("BBB");
var actual = scc.MethodB();
Assert.Equal("BBB", actual);
}
然而,这是毫无意义的,因为你可以写下这个:
[Fact]
public void Reduction()
{
var scc = Substitute.For<SomeConcreteClass>();
scc.MethodB().Returns("BBB");
var actual = scc.MethodB();
Assert.Equal("BBB", actual);
}
换句话说,AutoFixture在该变通办法中实际上并没有做任何事情。
我可以想象真正的问题是,在实际使用中,所讨论的具体类具有您希望用数据填充的其他成员或构造函数数据。问题在于,由于NSubstitute的设计方式,我不知道你有什么方法可以声明性地要求替换&#39 ;;你必须使用Substitute.For
方法,然后完全缩短AutoFixture挂钩进程并添加自己行为的能力。
使用Moq,这是可能的,因为在OP中,您不会向SomeConcreteClass
对象询问AutoFixture,而是要求Mock<SomeConcreteClass>
,并且可以使AutoFixture区分。
换句话说,Moq遵循Zen of Python 显式优于隐式,这使得它可扩展到不容易用NSubstitute实现的程度。出于这个原因,我一直认为Moq拥有更好的API。