Mon domaine se compose de nombreuses classes immuables simples comme celle-ci:
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;
}
}
L'écriture des vérifications nulles et de l'initialisation des propriétés devient déjà très fastidieuse mais actuellement j'écris des tests unitaires pour chacune de ces classes pour vérifier que la validation des arguments fonctionne correctement et que toutes les propriétés sont initialisées. Cela ressemble à un travail extrêmement ennuyeux avec des avantages incommensurables.
La vraie solution serait que C # prenne en charge nativement les types de référence immuables et non nullables. Mais que puis-je faire pour améliorer la situation entre-temps? Vaut-il la peine d'écrire tous ces tests? Serait-ce une bonne idée d'écrire un générateur de code pour de telles classes pour éviter d'écrire des tests pour chacune d'elles?
Voici ce que j'ai maintenant basé sur les réponses.
Je pourrais simplifier les vérifications nulles et l'initialisation des propriétés pour ressembler à ceci:
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));
En utilisant l'implémentation suivante de 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;
}
}
Test des contrôles null est facile à l' aide du GuardClauseAssertion
de AutoFixture.Idioms
(merci pour la suggestion, Esben Skov Pedersen ):
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(typeof(Address).GetConstructors());
Cela pourrait être encore plus compressé:
typeof(Address).ShouldNotAcceptNullConstructorArguments();
En utilisant cette méthode d'extension:
public static void ShouldNotAcceptNullConstructorArguments(this Type type)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(type.GetConstructors());
}