8
votes

Comment est-ce que l'unité teste une fonction C # qui retourne une fonction ?

J'ai une classe contenant une méthode qui renvoie un objet de résultat qui contient une propriété de type FUNC.

// Arrange
ListController controller = new ListController(domain);
// Act
Result actual = controller.DefaultAction();
// Assert
Func<Result> expected = () => new ProductsController(domain).ListAction();
Assert.That(actual.NextAction, Is.EqualTo(expected));


0 commentaires

5 Réponses :


2
votes

Pourquoi ne pas invoquer le Func code> et comparer les valeurs retournées?

var actualValue = actual.NextAction();
var expectedValue = expected();
Assert.That(actualValue, Is.EqualTo(expectedValue));


6 commentaires

Parce que le Func renvoie un autre objet de résultat, avec les mêmes problèmes!


Ensuite, vous devez mettre en œuvre quelque chose qui identifie le résultat et déterminer l'égalité en fonction de celle-ci.


Comme une chaîne arbitraire décrivant l'intention du Func?


Il n'y a pas de champs d'identification dans la classe de résultat. Il est destiné à être un espace réservé pour appeler de manière dynamique la classe / méthode suivante en fonction d'une décision dans la classe / méthode actuelle.


S'il n'y a rien dans le domaine qui définit une identité de l'objet, une chaîne arbitraire devrait faire. Mais je soupçonne que vous essayez de tester une unité de test d'unité qui n'est pas destiné à être testé unitaire - à la fin, le programme doit avoir une valeur disponible et vous devez affirmer sur les valeurs et non sur les fonctionnalités qui leur fournissent.


Dans un objet dont la responsabilité est de décider de la prochaine action, j'aurais pensé que l'unité teste cette décision était d'une importance primordiale.



0
votes

Si vous FUNC renvoie toujours le même résultat que vous pouvez tester quel objet est renvoyé par la fonction.


1 commentaires

Malheureusement, le FUNC renvoie un résultat qui ne contient qu'un autre Func



2
votes

Je ne suis pas au courant d'un moyen facile de regarder à l'intérieur d'une Lambda (autre que d'utiliser des arbres d'expression comme vous l'avez dit), mais il est possible de comparer les délégués s'ils ont été attribués à un Groupe de méthodes à la place.

var result1 = new Result {
    NextAction = new ProductsController(domain).ListAction };
var result2 = new Result {
    NextAction = new ProductsController(domain).ListAction };

//objects are different
Assert.That(result1, Is.Not.EqualTo(result2));

//delegates are different
Assert.That(result1.NextAction, Is.Not.EqualTo(result2.NextAction));

//methods are the same
Assert.That(result1.NextAction.Method, Is.EqualTo(result2.NextAction.Method));


1 commentaires

Oui, cela ressemble beaucoup à des tests pour l'enregistrement des événements, ou tout autre usage de délégué. Bien que cela puisse être le meilleur compromis, l'intention d'origine consistait à inclure l'instanciation de produitsController dans le cadre d'invoquer NextAction.



0
votes

Eh bien, il apparaît que l'unité teste le contenu d'un FUNC code> dépasse la plage normale des tests de l'unité. Un Func code> représente le code compilé et ne peut donc pas être inspecté sans recourir à l'analyse de MSIL. Dans cette situation, il est donc nécessaire de revenir sur les délégués et les types instanciés (comme suggéré par Nathan Baulch) ou d'utiliser des arbres d'expression à la place.

mon arbre d'expression équivalent ci-dessous: P>

// Arrange
ListController controller = new ListController(domain);
// Act
Result actual = controller.DefaultAction();
// Assert
MethodCallExpression methodExpr = (MethodCallExpression)actual.NextAction.Body;
NewExpression newExpr = (NewExpression)methodExpr.Object;
Assert.That(newExpr.Type, Is.EqualTo(typeof(ProductsController)));
Assert.That(methodExpr.Method.Name, Is.EqualTo("ListAction"));


0 commentaires

0
votes

Si je comprends bien le problème, la suivante peut avoir une implémentation de Lambda différente, ce qui nécessite des tests.

Dans l'exemple ci-dessous, je comparais les méthodes il octets. Utilisation de la réflexion, obtenez les informations sur la méthode et les octets du corps dans un tableau. Si les matrices d'octets correspondent, les Lambda sont les mêmes.

Il y a beaucoup de situations que cela ne manipulez pas, mais s'il s'agit simplement de la question de comparer deux Lambda qui devrait être exactement la même, cela fonctionnera. Désolé c'est dans le Mstest :) xxx


2 commentaires

Oui, cela pourrait être une possibilité. Cela pourrait réellement fonctionner, sauf que le code passe dans le paramètre "Domaine" au constructeur de produitsController qui se résout à différents IL. Je crois que cela est dû à la classe créée pour accueillir l'expression de la Lambda compilée.


Une solution autour de ce serait de «capturer» le code d'octet correct de l'IL du code d'exécution et correspond à cela. Le test finirait par être très spécifique aux conditions testées, mais fonctionnerait. Ce n'est pas mauvais si vous avez un test pour cet état spécifique, mais je ne voudrais pas beaucoup d'entre eux.