I'm reading a lot of documentation and examples about how to properly unit test things combining the three components in the title. I came up with a test method for a method on my business logic, but it feels very clunky and dirty.
I'd like to get some feedback from people more experienced on this topic to see how I can improve it.
Here's the code, explanation follows:
[Fact]
public void ShouldGetItemWithSameId()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var facade = fixture.Freeze<Mock<IDataFacade>>();
facade.Setup(c => c.Get(It.IsAny<int>())).Returns((int i) => new Item { Key = i });
var sut = fixture.Create<BusinessLogic>();
var expected = fixture.Create<int>();
Assert.Equal(expected, sut.Get(expected).Key);
}
My BusinessLogic
class takes an IDataFacade
as constructor parameter, which is responsible in its Get(int)
method to retrieve the item with the same Id, pretty basic stuff.
I freeze the IDataFacade
mock and I set it up to construct an object matching the Id in It.IsAny<int>
. I then create my SUT and test it. Works fine.
I'd like to understand if I can improve things considering the following:
Query
method that takes a class containing a lot of properties that will be used as filters on matching properties on the type being queried. In this case I wouldn't know how to properly do the "Setup" part of the mock, since I have to initialize all, or close to all, the properties of the returned type, and in this scenario it's not a single Item but a whole collectionI have some other tests using Theory
with AutoMoqData
but I was unable to achieve this test (and I think the more complex ones) using that approach, so I switched back to plain Fact
with manually instantiated fixture.
Any help will be extremely appreciated.
AutoFixture is a library that you can use alongside your testing framework to reduce the amount of boilerplate test code you need to write and thus improve your productivity. At its core, AutoFixture helps you setup your tests by generating anonymous test data for you.
Moq and xUnit belong to "Testing Frameworks" category of the tech stack. xUnit is an open source tool with 2.62K GitHub stars and 610 GitHub forks. Here's a link to xUnit's open source repository on GitHub.
xUnit.net offers several methods for sharing this setup and cleanup code, depending on the scope of things to be shared, as well as the expense associated with the setup and cleanup code.
AutoFixture is an open source library for . NET designed to minimize the 'Arrange' phase of your unit tests in order to maximize maintainability.
Overall, the original test looks good. It's not possible nor easy to extract the setup of Stubs and Mocks out of the test, in a generic fashion.
What you can do though, is minimize the Arrange phase of the test. Here's the original test re-written using AutoFixture.Xunit's own unit-testing DSL:
[Theory, TestConventions]
public void ShouldGetItemWithSameId(
[Frozen]Mock<IDataFacade> facadeStub,
BusinessLogic sut,
int expected)
{
facadeStub
.Setup(c => c.Get(It.IsAny<int>()))
.Returns((int i) => new Item { Key = i });
var result = sut.Get(expected);
var actual = result.Key;
Assert.Equal(expected, actual);
}
The TestConventions
attribute is defined as:
public class TestConventionsAttribute : AutoDataAttribute
{
public TestConventionsAttribute()
: base(new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
HTH
Sample types used in the example:
public class Item
{
public int Key { get; set; }
}
public interface IDataFacade
{
Item Get(int p);
}
public class BusinessLogic
{
private readonly IDataFacade facade;
public BusinessLogic(IDataFacade facade)
{
this.facade = facade;
}
public Item Get(int p)
{
return this.facade.Get(p);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With