単体テストでMoqを直接使用して自分自身をモックIBuilderFactory
およびインスタンス化すると、のメソッドが1 回だけ呼び出されるBuilderService
ことを検証する合格テストを取得できます。Create()
IBuilderFactory
ただし、AutoMoqCustomizationでAutofixtureを使用し、 のモックをフリーズしてIBuilderFactory
でインスタンス化BuilderService
するとfixture.Create<BuilderService>
、次の例外が発生します。
System.ArgumentException: クラスのプロキシをインスタンス化できません: OddBehaviorTests.CubeBuilder. パラメーターなしのコンストラクターが見つかりませんでした。パラメータ名: constructorArguments
私が封印した場合(によって呼び出されるCubeBuilder
封印されたクラスに置き換えることで表されます)、テストは AutoFixture を使用して AutoMoqCustomization に合格し、例外はスローされません。SealedCubeBuilder
IBuilderFactoryForSealedBuilder.Create()
何か不足していますか?Moq を直接使用してテストに合格するので、これは Autofixture および/または AutoMoqCustomization に関連していると思います。これは望ましい動作ですか?もしそうなら、なぜですか?
再現するために、私は使用しています:
using Moq;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoMoq;
using Xunit;
動作を示す 4 つのテストを次に示します。
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 { }