J'ai un test unitaire, qui ressemble à ceci:
[Test]
public void Should_create_person()
{
Assert.DoesNotThrow(() => new Person(Guid.NewGuid(), new DateTime(1972, 01, 01));
}
J'affirme qu'un objet Personne est créé ici, c'est-à-dire que la validation n'échoue pas. Par exemple, si le Guid est nul ou si la date de naissance est antérieure au 01/01/1900, la validation échouera et une exception sera levée (ce qui signifie que le test échoue).
Le constructeur ressemble à ceci:
public Person(Id id, DateTime dateOfBirth) :
base(id)
{
if (dateOfBirth == null)
throw new ArgumentNullException("Date of Birth");
elseif (dateOfBith < new DateTime(1900,01,01)
throw new ArgumentException("Date of Birth");
DateOfBirth = dateOfBirth;
}
Est-ce une bonne idée pour un test?
Remarque : je suis une approche classique des tests unitaires du modèle de domaine si cela a une incidence.
c#
unit-testing
constructors
w0051977
la source
la source
Should_create_person
? Qu'est-ce qui devrait créer une personne? Donnez-lui un nom significatif, commeCreating_person_with_valid_data_succeeds
.Réponses:
C'est un test valide (bien que plutôt zélé) et je le fais parfois pour tester la logique du constructeur, cependant, comme Laiv l'a mentionné dans les commentaires, vous devriez vous demander pourquoi.
Si votre constructeur ressemble à ceci:
Y a-t-il beaucoup d'intérêt à tester s'il lance? Que les paramètres soient correctement attribués, je peux comprendre, mais votre test est plutôt exagéré.
Cependant, si votre test fait quelque chose comme ceci:
Ensuite, votre test devient plus pertinent (car vous lancez des exceptions quelque part dans le code).
Une chose que je dirais, c'est généralement une mauvaise pratique d'avoir beaucoup de logique dans votre constructeur. La validation de base (comme les vérifications nulles / par défaut que je fais ci-dessus) est correcte. Mais si vous vous connectez à des bases de données et chargez les données de quelqu'un, c'est là que le code commence à vraiment sentir ...
Pour cette raison, si votre constructeur mérite d'être testé (car il y a beaucoup de logique), peut-être que quelque chose d'autre ne va pas.
Vous allez presque certainement avoir d'autres tests couvrant cette classe dans les couches de logique métier, les constructeurs et les affectations de variables vont presque certainement obtenir une couverture complète de ces tests. Par conséquent, il peut être inutile d'ajouter des tests spécifiques spécifiquement pour le constructeur. Cependant, rien n'est noir et blanc et je n'aurais rien contre ces tests si je les examinais - mais je me demanderais s'ils ajoutent beaucoup de valeur au-delà des tests ailleurs dans votre solution.
Dans votre exemple:
Vous faites non seulement la validation, mais vous appelez également un constructeur de base. Pour moi, cela fournit plus de raisons d'avoir ces tests car ils ont maintenant la logique constructeur / validation divisée en deux classes, ce qui diminue la visibilité et augmente le risque de changement inattendu.
TLDR
Ces tests ont une certaine valeur, mais la logique de validation / affectation est susceptible d'être couverte par d'autres tests dans votre solution. S'il y a beaucoup de logique dans ces constructeurs qui nécessite des tests importants, cela me suggère qu'il y a une mauvaise odeur de code qui se cache là-dedans.
la source
PersonBirthdate
) qui effectue la validation de la date de naissance. De même, laGuid
vérification pourrait être implémentée sur laId
classe. Cela signifie que vous n'avez plus vraiment besoin d'avoir cette logique de validation dans lePerson
constructeur car il n'est pas possible d'en construire une avec des données invalides - sauf pour lesnull
références. Bien sûr, vous devez passer des tests pour les deux autres classes :)Déjà une bonne réponse ici, mais je pense qu'une chose supplémentaire mérite d'être mentionnée.
Quand on fait TDD "à la livre", il faut d'abord écrire un test qui appelle le constructeur, avant même que le constructeur soit implémenté. Ce test pourrait en fait ressembler à celui que vous avez présenté, même s'il n'y aurait aucune logique de validation à l'intérieur de l'implémentation du constructeur.
Notez également que pour TDD, il faut d'abord écrire un autre test comme
avant d' ajouter la vérification pour
DateTime(1900,01,01)
le constructeur.Dans le contexte TDD, le test illustré est parfaitement logique.
la source