My domain consists of lots of simple immutable classes like this:
public class Person
{
public string FullName { get; }
public string NameAtBirth { get; }
public string TaxId { get; }
public PhoneNumber PhoneNumber { get; }
public Address Address { get; }
public Person(
string fullName,
string nameAtBirth,
string taxId,
PhoneNumber phoneNumber,
Address address)
{
if (fullName == null)
throw new ArgumentNullException(nameof(fullName));
if (nameAtBirth == null)
throw new ArgumentNullException(nameof(nameAtBirth));
if (taxId == null)
throw new ArgumentNullException(nameof(taxId));
if (phoneNumber == null)
throw new ArgumentNullException(nameof(phoneNumber));
if (address == null)
throw new ArgumentNullException(nameof(address));
FullName = fullName;
NameAtBirth = nameAtBirth;
TaxId = taxId;
PhoneNumber = phoneNumber;
Address = address;
}
}
Writing the null checks and property initialization is already getting very tedious but currently I write unit tests for each of these classes to verify that argument validation works correctly and that all properties are initialized. This feels like extremely boring busywork with incommensurate benefit.
The real solution would be for C# to support immutability and non-nullable reference types natively. But what can I do to improve the situation in the meantime? Is it worth writing all these tests? Would it be a good idea to write a code generator for such classes to avoid writing tests for each one of them?
Here is what I have now based on the answers.
I could simplify the null checks and property initialization to look like this:
FullName = fullName.ThrowIfNull(nameof(fullName));
NameAtBirth = nameAtBirth.ThrowIfNull(nameof(nameAtBirth));
TaxId = taxId.ThrowIfNull(nameof(taxId));
PhoneNumber = phoneNumber.ThrowIfNull(nameof(phoneNumber));
Address = address.ThrowIfNull(nameof(address));
Using the following implementation by Robert Harvey:
public static class ArgumentValidationExtensions
{
public static T ThrowIfNull<T>(this T o, string paramName) where T : class
{
if (o == null)
throw new ArgumentNullException(paramName);
return o;
}
}
Testing the null checks is easy using the GuardClauseAssertion
from AutoFixture.Idioms
(thanks for the suggestion, Esben Skov Pedersen):
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(typeof(Address).GetConstructors());
This could be compressed even further:
typeof(Address).ShouldNotAcceptNullConstructorArguments();
Using this extension method:
public static void ShouldNotAcceptNullConstructorArguments(this Type type)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(type.GetConstructors());
}