When I use Moq directly to mock IBuilderFactory
and instantiate BuilderService
myself in a unit test, I can get a passing test which verifies that the Create()
method of IBuilderFactory
is called exactly once.
However, when I use Autofixture with AutoMoqCustomization, freezing a mock of IBuilderFactory
and instantiating BuilderService
with fixture.Create<BuilderService>
, I get the following exception:
System.ArgumentException: Can not instantiate proxy of class: OddBehaviorTests.CubeBuilder. Could not find a parameterless constructor. Parameter name: constructorArguments
If I make CubeBuilder
sealed (represented by replacing it with the sealed class SealedCubeBuilder
which is called by IBuilderFactoryForSealedBuilder.Create()
, the test passes using AutoFixture with AutoMoqCustomization, with no exception thrown.
Am I missing something? Since I get passing tests using Moq directly, I believe this is related to Autofixture and/or AutoMoqCustomization. Is this the desired behavior? If so, why?
To reproduce, I'm using:
using Moq;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoMoq;
using Xunit;
Here are the four tests illustrating the behavior:
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());
}
}
Here are the required classes:
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 { }