Repetitive code in unit-tests
autofixture, c#, moq, nunit, unit-testing
Solution
You can create a composite Customization that will customize the fixture by using all contained customizations.
public class HttpMocksCustomization : CompositeCustomization
{
public HttpMocksCustomization()
: base(
new AutoMoqCustomization(),
new HttpWebClientWrapperMockCustomization(),
new HttpWebResponseWrapperMockCustomization()
// ...
)
{
}
}
Each customization can be defined as follow:
public class HttpWebClientWrapperMockCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
var mock = new Mock<IHttpWebClientWrapper>();
mock.Setup(m => m.GetResponse()).Returns(httpResponseMock.Object);
fixture.Inject(mock);
}
}
public class HttpWebResponseWrapperMockCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
var mock = new Mock<IHttpWebResponseWrapper>();
mock.Setup(m => m.StatusCode).Returns(HttpStatusCode.OK);
fixture.Inject(mock);
}
}
// The rest of the Customizations.
Then inside the test method you can do this:
var fixture = new Fixture().Customize(new HttpMocksCustomization());
That way, when you request a Mock instance you don't have to repeat the setup steps. The one we customized earlier will be returned:
var httpClientMock = fixture.Freeze<Mock<IHttpWebClientWrapper>>();
However, if you use xUnit.net, things can be simplified even further.
You can create an AutoDataAttribute-derived type to provide auto-generated data specimens generated by AutoFixture as an extention to xUnit.net's Theory attribute:
public class AutoHttpMocksDataAttribute : AutoDataAttribute
{
public AutoHttpMocksDataAttribute()
: base(new Fixture().Customize(new HttpMocksCustomization()))
{
}
}
Then, in your test method you can pass the Mocks as arguments:
[Theory, AutoHttpMocksData]
public void MyTestMethod([Freeze]Mock<IHttpWebClientWrapper> httpClientMock, [Freeze]Mock<IHttpWebResponseWrapper> httpResponseMock)
{
// ...
}
Problem
We find ourselves coding repetitive fixture/mock setups in many test-cases - like this case: ``` var fixture = new Fixture().Customize(new AutoMoqCustomization()); var encodingMock = fixture.Freeze<Mock<IEncodingWrapper>>(); var httpClientMock = fixture.Freeze<Mock<IHttpWebClientWrapper>>(); var httpResponseMock = fixture.Freeze<Mock<IHttpWebResponseWrapper>>(); var httpHeaderMock = fixture.Freeze<Mock<IHttpHeaderCollectionWrapper>>(); var etag = fixture.CreateAnonymous<string>(); byte[] data = fixture.CreateAnonymous<byte[]>(); Stream stream = new MemoryStream(data); encodingMock.Setup(m => m.GetBytes(It.IsAny<string>())).Returns(data); httpHeaderMock.SetupGet(m => m[It.IsAny<string>()]).Returns(etag).Verifiable(); httpClientMock.Setup(m => m.GetResponse()).Returns(httpResponseMock.Object); httpResponseMock.Setup(m => m.StatusCode).Returns(HttpStatusCode.OK); httpResponseMock.SetupGet(m => m.Headers).Returns(httpHeaderMock.Object); httpResponseMock.Setup(m => m.GetResponseStream()).Returns(stream); ``` As per the idea that the tests should be self-contained and readable from start to end we dont use magical Setup/Teardown methods. Can we in any way (AutoFixture customizations, helper methods) reduce the "grunt work" of these tests?