Мій домен складається з безлічі простих незмінних класів на кшталт цього:
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з AutoFixture.Idioms(спасибі за пропозицію, Esben Skov Pedersen ):
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());
}