First of all, I'm going to answer this question under the assumption that TypesWithoutPublicCtrs
is defined as in the OP's GitHub repository:
public class TypesWithoutPublicCtrs
{
private readonly IMyInterface _mi;
public TypesWithoutPublicCtrs(IMyInterface mi)
{
_mi = mi;
}
}
The reason I'm explicitly calling this out is because the name is a red herring: it does have a public constructor; it just doesn't have a default constructor.
Anyway, AutoFixture easily deals with the absence of default constructors. The problem here isn't the TypesWithoutPublicCtrs
class itself, but rather the IMyInterface
interface. Interfaces are problematic because they can't be initialized at all.
Thus, you need to somehow map an interface to a concrete class. There are various ways to do that.
One-off solution
Once in a while, I use this one-off solution, although I find it ugly. However, it's easy and doesn't require a lot of sophisticated setup.
[Theory, AutoData]
public void TestSomething(
[Frozen(As = typeof(IMyInterface))]FakeMyInterface dummy,
TypesWithoutPublicCtrs sut)
{
// use sut here, and ignore dummy
}
This isn't particularly nice, because it relies on a side-effect of the [Frozen]
attribute, but it works as a self-contained one-off solution.
Convention
However, I much rather like to make a convention out of it, so that the same convention applies for all tests in a test suite. A test using such a convention could look like this:
[Theory, MyTestConventions]
public void TestSomething(TypesWithoutPublicCtrs sut)
{
// use sut here; it'll automatically have had FakeMyInterface injected
}
The [MyTestConventions]
attribute could look like this:
public class MyTestConventionsAttribute : AutoDataAttribute
{
public MyTestConventionsAttribute() :
base(new Fixture().Customize(new MyTestConventions())
{}
}
The MyTestConventions
class must implement the interface ICustomization
. There are several ways in which you can map IMyInterface
to FakeMyInterface
; here's one:
public class MyTestConventions : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new TypeRelay(typeof(IMyInterface), typeof(FakeMyInterface)));
}
}
Auto-Mocking
However, you may get tired of having to create and maintain all those Fakes, so you can also turn AutoFixture into an Auto-Mocking Container. There are various options for doing that, leveraging Moq, NSubstitute, FakeItEasy and Rhino Mocks.