Мой домен состоит из множества простых неизменяемых классов, таких как:
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;
}
}
Написание нулевых проверок и инициализация свойств уже становятся очень утомительными, но в настоящее время я пишу модульные тесты для каждого из этих классов, чтобы убедиться, что проверка аргументов работает правильно и что все свойства инициализированы. Это похоже на чрезвычайно скучную занятую работу с несоизмеримой выгодой.
Реальным решением было бы C # изначально поддерживать неизменяемость и необнуляемые ссылочные типы. Но что я могу сделать, чтобы улучшить ситуацию? Стоит ли писать все эти тесты? Было бы хорошей идеей написать генератор кода для таких классов, чтобы избежать написания тестов для каждого из них?
Вот что я сейчас основал на ответах.
Я мог бы упростить нулевые проверки и инициализацию свойств, чтобы они выглядели так:
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));
Используя следующую реализацию Роберта Харви :
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;
}
}
Тестирование нулевых проверок легко с помощью GuardClauseAssertion
from AutoFixture.Idioms
(спасибо за предложение, Эсбен Сков Педерсен ):
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(typeof(Address).GetConstructors());
Это может быть сжато еще дальше:
typeof(Address).ShouldNotAcceptNullConstructorArguments();
Используя этот метод расширения:
public static void ShouldNotAcceptNullConstructorArguments(this Type type)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(type.GetConstructors());
}