当我在单元测试中直接使用Moq来模拟IBuilderFactory
和实例化BuilderService
自己时,我可以获得一个通过测试,该测试验证该Create()
方法IBuilderFactory
只被调用了一次。
但是,当我将Autofixture与AutoMoqCustomization一起使用时,冻结模拟IBuilderFactory
并用 实例化BuilderService
,fixture.Create<BuilderService>
我得到以下异常:
System.ArgumentException:无法实例化类的代理:OddBehaviorTests.CubeBuilder。找不到无参数构造函数。参数名称:constructorArguments
如果我进行CubeBuilder
密封(通过将其替换为由 调用的密封类SealedCubeBuilder
来表示IBuilderFactoryForSealedBuilder.Create()
,则使用带有 AutoMoqCustomization 的 AutoFixture 通过测试,不会引发异常。
我错过了什么吗?由于我直接使用 Moq 通过测试,我相信这与 Autofixture 和/或 AutoMoqCustomization 有关。这是期望的行为吗?如果是这样,为什么?
为了重现,我正在使用:
using Moq;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoMoq;
using Xunit;
以下是说明该行为的四个测试:
public class BuilderServiceTests {
[Fact]
public void CubeBuilderFactoryCreateMethodShouldBeCalled_UsingMoq() {
var factory = new Mock<IBuilderFactory>();
var sut = new BuilderService(factory.Object);
sut.Create();
factory.Verify(f => f.Create(), Times.Once());
}
[Fact]
public void CubeBuilderFactoryCreateMethodShouldBeCalled_UsingAutoFixture() {
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var factory = fixture.Freeze<Mock<IBuilderFactory>>();
var sut = fixture.Create<BuilderService>();
sut.Create(); // EXCEPTION THROWN!!
factory.Verify(f => f.Create(), Times.Once());
}
[Fact]
public void SealedCubeBuilderFactoryCreateMethodShouldBeCalled_UsingMoq() {
var factory = new Mock<IBuilderFactoryForSealedBuilder>();
var sut = new BuilderServiceForSealedBuilder(factory.Object);
sut.Create();
factory.Verify(f => f.Create(), Times.Once());
}
[Fact]
public void SealedCubeBuilderFactoryCreateMethodShouldBeCalled_UsingAutoFixture() {
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var factory = fixture.Freeze<Mock<IBuilderFactoryForSealedBuilder>>();
var sut = fixture.Create<BuilderServiceForSealedBuilder>();
sut.Create();
factory.Verify(f => f.Create(), Times.Once());
}
}
以下是所需的类:
public interface IBuilderService { IBuilder Create(); }
public class BuilderService : IBuilderService {
private readonly IBuilderFactory _factory;
public BuilderService(IBuilderFactory factory) { _factory = factory; }
public IBuilder Create() { return _factory.Create(); }
}
public class BuilderServiceForSealedBuilder : IBuilderService {
private readonly IBuilderFactoryForSealedBuilder _factory;
public BuilderServiceForSealedBuilder(IBuilderFactoryForSealedBuilder factory) { _factory = factory; }
public IBuilder Create() { return _factory.Create(); }
}
public interface IBuilderFactoryForSealedBuilder { SealedCubeBuilder Create(); }
public interface IBuilderFactory { CubeBuilder Create(); }
public interface IBuilder { void Build(); }
public abstract class Builder : IBuilder {
public void Build() { } // build stuff
}
public class CubeBuilder : Builder {
private Cube _cube;
public CubeBuilder(Cube cube) { _cube = cube; }
}
public sealed class SealedCubeBuilder : Builder {
private Cube _cube;
public SealedCubeBuilder(Cube cube) { _cube = cube; }
}
public class Cube { }