Autofixture: Traitez les délégués comme des faux avec FakeItEasy

Créé le 16 févr. 2018  ·  15Commentaires  ·  Source: AutoFixture/AutoFixture

Pour autant que je sache, AutoFixture traite automatiquement les interfaces et les types abstraits comme des objets fictifs. Je pense que c'est une bonne idée d'inclure également les types de délégués dans cette liste.

enhancement good first issue

Commentaire le plus utile

Sorti en v4.2.0 ! Autoriser:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

Tous les 15 commentaires

Tout d'abord, pourriez-vous préciser avec quel framework moqueur vous travaillez ? Nous avons quelques intégrations (Moq, NSubsitute, FakeItEasy), donc ce n'est pas clair. Pour autant que je sache, les délégués sont déjà pris en charge par l'intégration Moq (au moins cela est mentionné dans #742).

Aussi autant que je sache, AutoFixture a son propre mécanisme de génération de délégués. Avez-vous des problèmes avec cela?

@zvirja J'utilise FakeItEasy. Je change donc le titre du problème
Le code suivant renvoie un Fake après l'application de la personnalisation :
var myFake= fixture.Create<ISomeInterface>();

Cependant, ce qui suit n'est pas le cas :
var myFake= fixture.Create<Func<int,int>>();

Le code ci-dessus renvoie simplement un délégué factice non faux.

De plus, les plantages suivants avec une erreur :

var myFake= fixture.Create<Fake<Func<int,int>>>();

AutoFixture.ObjectCreationExceptionWithPath
HRésultat=0x80131500
Message=AutoFixture n'a pas pu créer une instance à partir de System.IntPtr car la création a échoué de manière inattendue avec une exception. Veuillez vous référer à l'exception interne pour rechercher la cause première de l'échec.

Chemin de la demande :
FakeItEasy.Fake 1[System.Func 2[System.Int32,System.Int32]]
Méthode IntPtr
System.IntPtr

Messages d'exception internes :
AutoFixture.Kernel.IllegalRequestException : une demande d'IntPtr a été détectée. Il s'agit d'une ressource dangereuse qui fera planter le processus si elle est utilisée, la demande est donc refusée. Une source commune de demandes IntPtr sont les demandes de délégués tels que Funcou Action. Si tel est le cas, la solution de contournement attendue consiste à personnaliser (enregistrer ou injecter) le type incriminé en spécifiant une stratégie de création appropriée.

Source=
Trace de la pile:

Exception intérieure 1 :
IllegalRequestException : une demande d'IntPtr a été détectée. Il s'agit d'une ressource dangereuse qui fera planter le processus si elle est utilisée, la demande est donc refusée. Une source commune de demandes IntPtr sont les demandes de délégués tels que Funcou Action. Si tel est le cas, la solution de contournement attendue consiste à personnaliser (enregistrer ou injecter) le type incriminé en spécifiant une stratégie de création appropriée.

@OnurGumus J'ai brièvement étudié ce problème et il ne semble pas que FakeItEasy prenne en charge la moquerie des délégués. Les délégués ne sont pas mentionnés dans leur documentation.

J'ai également testé le code suivant et il a échoué avec une exception (ce qui prouve que cette fonctionnalité n'est pas prise en charge):
c# A.Fake<Func<int, int>>();

Par conséquent, il ne semble pas qu'AutoFixture puisse également faire quelque chose à ce sujet.

Pourriez-vous s'il vous plaît décrire le comportement souhaité plus en détail? Il est très facile de simuler un délégué, car cela pourrait être spécifié via une expression lambda primitive, alors pourquoi avez-vous besoin de simulacres ?

@zvirja , FakeItEasy prend certainement en charge les faux pour les délégués :
image

@blairconrad Pourriez-vous, s'il vous plaît, trouver quelques minutes et nous éclairer à ce sujet ? FakeItEasy prend-il en charge la moquerie des délégués ? Si oui, quelle est la syntaxe ? Mon échantillon ci-dessus a échoué pour moi, mais il se peut que j'aie raté quelque chose... :confused:

Merci :clin d'oeil:

@zvirja , heureux de. Comme le dit @OnurGumus , FakeItEasy falsifiera volontiers les délégués (et j'ai créé un problème pour documenter cela).
Cependant, AutoFakeItEasy ne s'est jamais soucié des faux délégués.

Lorsque vous simulez un Fake<Func<int, int>> , par exemple, FakeItEasyMethodQuery.SelectMethods échoue car il ne considère pas le cas Fake<T>T est un délégué. Le changement très naïf ci-dessous rectifie cela.

@@ -33,7 +33,7 @@ namespace Ploeh.AutoFixture.AutoFakeItEasy
             }

             var fakeType = type.GetFakedType();
-            if (fakeType.IsInterface)
+            if (fakeType.IsInterface || fakeType.IsSubclassOf(typeof(Delegate)))
             {
                 return new[] { new ConstructorMethod(type.GetDefaultConstructor()) };
             }

Ensuite, je peux créer et utiliser un Fake<Func<int, int>> .

En ce qui concerne la création d'un Func<int, int> , je l'ai essayé rapidement et j'ai découvert que le luminaire utilisait DelegateGenerator pour créer un délégué (non FakeItEasy).
Entre vous et moi, j'ai toujours été confus par l'architecture AutoFixture et la relation entre un constructeur et un relais et ainsi de suite, mais je peux continuer à explorer et voir où se situe l'écart.

Je suis revenu. Je peux comprendre. Le FakeItEasyRelay est ajouté aux collecteurs de résidus de l'appareil, mais le DelegateGenerator crée d'abord un délégué.
Une recherche rapide n'a pas révélé comment insérer le constructeur FakeItEasy plus tôt dans la chaîne, mais je ne cherche peut-être pas correctement.

Indépendamment de la façon dont cela se déroule, je serais heureux de soumettre un PR pour permettre la moquerie de Fake<TDelegate>TDelegate est un type délégué.

@blairconrad en tant

@blairconrad Merci pour les éclaircissements et pour votre enquête ! Je viens de vérifier une fois de plus et j'ai découvert que FakeItEasy créait effectivement les faux pour les délégués. Probablement, j'ai raté quelque chose dans mon test précédent 😖

Quant à la création d'un Func, je l'ai essayé rapidement et j'ai découvert que le luminaire utilisait DelegateGenerator pour créer un délégué (non FakeItEasy).

Ouais. Nous avons exactement le même problème avec Moq - AutoFixture intercepte ces demandes avant que le ResidueCollectors n'ait la possibilité d'intervenir.

Je suggère de résoudre ce problème de la manière suivante :

  • Étendre la requête de méthode pour prendre en charge les requêtes Fake<Delegate> ;
  • Ajoutez une nouvelle personnalisation, qui ajoutera un relais à la collection Customizations , afin que la demande de délégué soit gérée (relayée) _avant_ d'être traitée par le noyau AutoFixture. Cela signifie que cette fonctionnalité ne sera pas activée par défaut, mais les utilisateurs pourraient facilement l'activer à l'aide d'une personnalisation prédéfinie.

@blairconrad De plus, pourriez-vous s'il vous plaît décrire quel est l'avantage du faux délégué par rapport à celui créé par l'AutoFixture ? Pour l'instant, une seule chose me vient à l'esprit - vous pouvez les configurer en utilisant la fausse syntaxe de configuration de la bibliothèque.

Merci @zvirja.

Je pense que tu as raison. L'avantage d'un faux délégué serait qu'il pourrait être configuré à l'aide de la fausse syntaxe de configuration de bibliothèque.

Je suis heureux d'étendre la requête de méthode pour prendre en charge Fake<Delegate> , et j'ajouterai une personnalisation supplémentaire comme vous le dites, mais je me demande : est-ce que celui qui prend en charge Delegate assez bon ? Que se passe-t-il lorsque le prochain bogue signalé souhaite que IEnumerable ou Task ou IDictionary soient truqués par FakeItEasy ?

Oh, @zvirja a demandé une confirmation sur la syntaxe pour simuler un délégué. Il a maintenant été fusionné dans la documentation de FakeItEasy avec FakeItEasy/FakeItEasy#1321, mais pour être explicite :

```c#
var fakeDélégué = A.Fake>();

is the preferred syntax for clients, although "unnatural fakes" can be used:

```c#
var fakeDelegate = new Fake<Func<int, int>>();

Ce dernier est la façon dont la classe FakeItEasyBuilder créerait le Fake.

Fait amusant : les faux délégués n'étaient pas pris en charge jusqu'à la version 1.7.4257.42 (probablement commit FakeItEasy/FakeItEasy@edb4f61d0db0a84b68c7a9395f2661a58579d34a). Personnellement, je n'ai aucun problème à dire "vous n'obtenez pas ceci à moins que vous n'utilisiez au moins cette version de FakeItEasy". @zvirja ou autres, considérez-vous cela comme un problème ? Je vais devoir faire quelques ruses avec les tests unitaires pour m'assurer que nous ne cassons pas les tests AutoFakeItEasyUnitTest existants.
Sauf si vous souhaitez mettre à jour la version minimale de FakeItEasy pour ce correctif. Je ne le ferais probablement pas, d'autant plus que demander un délégué aurait de toute façon échoué sur ces versions.

@blairconrad Merci beaucoup pour votre travail là-dessus !

@zvirja ou autres, considérez-vous cela comme un problème ?

Pas du tout. Selon le SemVer que nous suivons ici, nous ne sommes pas autorisés à modifier la version de dépendance au sein de la même version majeure. Par conséquent, je dirais que la bonne étape serait d'ajouter un tel support pour les versions FakeItEasy qui prennent en charge la fonctionnalité. Plus tard, nous voudrons peut-être supprimer le support 1.x dans la v5 (pour plus de cohérence), mais cela ne se produira qu'à l'avenir.

Conversion de ce problème en une fonctionnalité, car nous avons accepté de procéder (et FakeItEasy prend en charge les délégués).

Sorti en v4.2.0 ! Autoriser:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

Cette page vous a été utile?
0 / 5 - 0 notes