I am trying to write some tests, I use xUnit.net, Moq, AutoFixture. I need to inject service to my test method:
[Theory, AutoData]
public void TestSmthCool(IService service)
{
}
The IService
has 3 dependencies which I want to mock. But, If I run the test I get error:
AutoFixture was unable to create an instance from Services.Interfaces.IService because it's an interface.
So, I fixed it in the following way:
[Theory, AutoData]
public void TestSmthCool()
{
var fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization());
fixture.Customizations.Add(
new TypeRelay(
typeof(IService),
typeof(MyService)
)
);
var s= fixture.Create<IService>();
}
But, how to setup TypeRelay
for all tests and inject service via method constructor?
If you wish to use MyService
for IService
, then you don't need AutoMoqCustomization
; i.e. this test passes:
[Fact]
public void TestSmthCool()
{
var fixture = new Fixture();
fixture.Customizations.Add(
new TypeRelay(
typeof(IService),
typeof(MyService)
)
);
var s = fixture.Create<IService>();
Assert.IsAssignableFrom<MyService>(s);
}
If you want to automate this, you can first package the TypeRelay
in an ICustomization
:
public class MyServiceCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new TypeRelay(
typeof(IService),
typeof(MyService)));
}
}
Then create an attribute that derives from AutoDataAttribute
:
public class MyServiceAutoDataAttribute : AutoDataAttribute
{
public MyServiceAutoDataAttribute() :
base(new Fixture().Customize(new MyServiceCustomization()))
{
}
}
You can then use that in all your tests:
[Theory, MyServiceAutoData]
public void CustomizedAutoDataBasedTest(IService s)
{
Assert.IsAssignableFrom<MyService>(s);
}
In general, I tend to create a code base-wide CompositeCustomization
that I apply indiscriminately to all tests.