Lorsque vous utilisez une AutoConfiguredMoqCustomization, la valeur renvoyée par le luminaire utilisé est mise en cache et la même valeur sera renvoyée à chaque invocation (je ne sais pas si cela est fait dans MockType.ReturnsUsingContext ou ailleurs, mais je vois un commentaire à ce sujet à la ligne 104 là-bas).
Le seul moyen que j'ai trouvé pour le remplacer est de passer une instance Frozen de la maquette en question dans la méthode de test et de remplacer la configuration avec une fonction appelant le luminaire :
someMock.Setup(it => it.SomeMethodReturningAString()).Returns(() => fixture.Create<string>())
Existe-t-il un moyen plus générique/plus intelligent de configurer les simulations générées automatiquement pour invoquer l'appareil chaque fois qu'une valeur est nécessaire à partir d'AutoFixture, autre que de configurer manuellement chaque invocation ?
L'idée derrière la mise en cache de la valeur du résultat était de rendre toutes les méthodes _pures_ par défaut, ce qui est considéré comme une bonne pratique.
Si le système testé s'attend à une fonction pure, mais reçoit une fonction impure, le test est susceptible d'aboutir à un faux positif. Par exemple
// This method will return the expected result *if* `GetInt` is pure.
int Double(IDependency dep) {
return dep.GetInt() + dep.GetInt();
}
Assert.Equal(dep.GetInt * 2, Double(dep));
D'un autre côté, si le système testé n'assume pas la pureté, lui donner une fonction pure ou impure ne devrait faire aucune différence.
Par conséquent, utiliser par défaut des fonctions pures avait du sens pour moi lorsque j'ai implémenté cette fonctionnalité.
Existe-t-il un moyen plus générique/plus intelligent de configurer les simulations générées automatiquement pour invoquer l'appareil chaque fois qu'une valeur est nécessaire à partir d'AutoFixture, autre que de configurer manuellement chaque invocation ?
Si vous devez le faire pour la méthode _one_, mais sur plusieurs tests, je le mettrais dans un IConfiguration
réutilisable.
Si vous voulez faire cela pour toutes les méthodes, sur plusieurs tests, vous aurez besoin d'un peu plus de travail :
ReturnsUsingContext
(IIRC, vous pouvez simplement copier l'implémentation actuelle et supprimer la ligne 104)MockVirtualMethodsCommand
et remplacez l'appel à ReturnsUsingContext
par un appel à votre nouvelle méthode.AutoConfiguredMoqCustomization
et remplacez l'instanciation de MockVirtualMethodsCommand
par une instanciation de votre nouvelle classe.Nous pourrions également penser à un moyen de rendre ce comportement configurable, mais je ne suis pas sûr que la demande soit suffisamment élevée pour le justifier. Un tel changement ne doit pas être pris à la légère, à mon avis - une personnalisation fine peut conduire à une complexité accidentelle. @ploeh , qu'en
J'avoue que je pensais que les doubles de test étaient configurés pour rappeler dans AutoFixture afin d'obtenir une valeur de retour. AutoFixture dispose déjà d'un mécanisme de gestion de la durée de vie (via ses fonctionnalités Freeze), je trouve donc un peu surprenant que AutoConfiguredMoqCustomization
implémente son propre gestionnaire de durée de vie et remplace ainsi la surface de contrôle fournie par AutoFixture.
C'est un très bon point, je n'ai jamais pensé à Freeze
cette façon. Changer le comportement de la personnalisation maintenant serait un changement décisif, je crois... pensez-vous qu'il devrait être modifié dans AutoFixture v4 ?
S'agit-il d'un comportement que nous avons documenté ou « promis » d'une manière ou d'une autre dans les tests ?
Étonnamment, non. J'étais à peu près sûr d'avoir couvert cela, mais il semble que non. Au moins, je n'ai trouvé aucun test couvrant cela, et la suppression de cette ligne n'a fait échouer aucun test. Cependant, selon l'OMI, il s'agit toujours d'un comportement observable, et il y aura probablement du code qui repose sur cela...
Point juste. Pourrait-il s'agir d'une valeur de configuration que nous définissons maintenant sur une valeur, puis la changeons lorsque nous passons à AutoFixture 4 ?
D'accord. Dans ce contexte, qu'entendez-vous exactement par « valeur de configuration » ? Le porter à un const à l'intérieur de la classe MockType
suffirait-il ? Par exemple, private const bool cacheReturnValues = true
puis if(cacheReturnValues) /**/
C'était un peu un commentaire jetable, je l'admets, donc je ne sais pas si ce serait pratiquement possible sans trop de changements. Ce que je voulais dire, cependant, c'était ceci:
@andreasnilsen aimerait changer le comportement maintenant, mais nous craignons que ce ne soit un changement donnerions à
Lorsque nous introduisons AutoFixture 4, nous modifions la configuration par défaut, de sorte que le comportement par défaut est alors que les valeurs de retour ne sont pas mises en cache. Ou peut-être supprimons-nous simplement cette option...
Quelque chose comme un booléen cacheReturnValues
pourrait être une façon de le faire, mais nous devrions permettre aux clients de changer la valeur, donc cela ne peut pas être private
.
(En outre, à moins que nous ne soyons absolument certains qu'il n'y aura exactement que deux valeurs, nous devrions considérer un enum
au lieu d'un bool
.)
Ah, j'ai d'abord pensé que vous vouliez dire un indicateur interne facile à repérer et à modifier dans la v4.
Les deux premières approches qui me viennent à l'esprit sont :
AutoConfiguredMoqCustomization
, qui serait ensuite propagé à MockVirtualMethodsCommand
et au MockType.ReturnsUsingContext
interne. Cela semble:Je me méfie de prendre des décisions de conception que nous pourrions regretter et avec lesquelles nous pourrions être coincés plus tard, donc votre expertise/expérience dans la maintenance de ce projet serait très appréciée.
Je pensais à quelque chose comme une stratégie ...
Ah oui, bien sûr ! Je suppose que j'étais obsédé par une "valeur de configuration" et que j'ai oublié de prendre du recul.
Je suis désolé pour la réponse tardive, j'ai été submergé - je vais y jeter un œil bientôt et je reviendrai avec une proposition de design.
Récemment, nous avons effectué la refactorisation de la personnalisation pour utiliser les propriétés pour le réglage de la personnalisation. Potentiellement, cette fonctionnalité pourrait être contrôlée comme suit (trouver le meilleur nom de paramètre) :
c#
new AutoMoqCustomization { CacheCallResults = false }
Sous le capot, nous pourrions mettre en œuvre cela via une stratégie différente comme celle qui a été conseillée ci-dessus.
Marquage avec une balise de saut, car cela devrait être relativement simple à mettre en œuvre.
@zvirja pourriez-vous m'aider un peu et je peux travailler sur celui-ci. Je ne sais pas par où commencer :)
@micheleissa Merci pour votre intérêt ! Je suggérerais simplement de lire le code source de AutoMoq
et de le déboguer pour comprendre les mécanismes internes. C'est très petit, donc ça ne devrait pas prendre beaucoup de temps...
Si vous avez une question plus précise, n'hésitez pas
Commentaire le plus utile
J'avoue que je pensais que les doubles de test étaient configurés pour rappeler dans AutoFixture afin d'obtenir une valeur de retour. AutoFixture dispose déjà d'un mécanisme de gestion de la durée de vie (via ses fonctionnalités Freeze), je trouve donc un peu surprenant que
AutoConfiguredMoqCustomization
implémente son propre gestionnaire de durée de vie et remplace ainsi la surface de contrôle fournie par AutoFixture.