I'm currently writing Unit Tests for my Domain project with xUnit, Moq and AutoFixture. Let's have a look at this Test Method:
[Theory]
public void SameValueAs_OnOtherHasDifferentEmail_ReturnsFalse()
{
Fixture fix = new Fixture();
var sut = fix.CreateAnonymous<CoreAddress>();
var other = new CoreAddress(
sut.Firstname,
sut.Lastname,
sut.Company,
sut.Street,
sut.City,
sut.ZIP,
"[email protected]");
Assert.False(sut.SameValueAs(other));
}
As you can see I'm testing the class CoreAddress and its SameValueAs Method. To test every possible case, I'd have to create the Test methods OnOtherHasDifferentFirstname , OnOtherHasDifferentLastname etc. Is this pattern okay? Can I somehow simplify this with regards to AutoFixture usage?
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.
Value Objects can be especially useful as a means for describing concepts in an application that have intrinsic rules but which are not themselves entities. In many applications, some concepts that are described as entities would be better off implemented as value objects.
A value object can reference other entities. For example, in an application that generates a route that describes how to get from one point to another, that route would be a value object.
A value object is an object without an explicit identifier. Its first main characteristic is that it does not require an identity. The second principal characteristic is that value objects must be immutable. It means that once value object properties are initialized, we can't change their values.
That approach is quite similar to what I would do myself. Given that almost all automated testing revolves around testing that some actual result is equal to some expected outcome, I never really understood why people wouldn't want to unit test equality itself.
With a value object like the above, it can easily become a bit tedious, as it leads to many tests which are all very similar.
One hack you could use with xUnit.net is this:
[Theory]
[InlineData("other first name", null, null, null, null, null, null)]
[InlineData(null, "other last name", null, null, null, null, null)]
[InlineData(null, null, "other company", null, null, null, null)]
[InlineData(null, null, null, "other street", null, null, null)]
[InlineData(null, null, null, null, "other city", null, null)]
[InlineData(null, null, null, null, null, "other zip", null)]
[InlineData(null, null, null, null, null, null, "[email protected]")]
public void EqualsIsFalseWhenAtLeastOneValueDiffers(
string firstName,
string lastName,
string company,
string street,
string city,
string zip,
string email)
{
Fixture fix = new Fixture();
var sut = fix.CreateAnonymous<CoreAddress>();
var other = new CoreAddress(
firstName ?? sut.Firstname,
lastName ?? sut.Lastname,
company ?? sut.Company,
street ?? sut.Street,
city ?? sut.City,
zip ?? sut.Zip,
email ?? sut.Email);
Assert.False(sut.Equals(other));
}
However, while it's compact, I'm not too keen on doing something like this, as the test itself has a cyclomatic complexity of 8 - which is about 7 too much... Only a slight misconfiguration of the input values could ruin the test and in the end produce either false positives or false negatives.
On the other hand, we're all programmers here, and if things become repetitive, what should we do?
Write some code to take away the tedium. This is basically what the AutoFixture.Idioms project is all about, and while it doesn't currently have an encapsulated test like the one above, it might get one in the future... it's open source, and we do occasionally take pull requests ;)
I wouldn't bother unit testing value objects equality as far as I'm concerned. If you really want to do it, there are ways of abstracting this kind of unit tests and make them much less tedious to write : http://kennethxu.blogspot.fr/2009/11/unit-test-value-object.html
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