J'utilise Moq et j'ai regardé Callback
mais je n'ai pas réussi à trouver un exemple simple pour comprendre comment l'utiliser.
Avez-vous un petit extrait de travail qui explique clairement comment et quand l'utiliser ?
J'utilise Moq et j'ai regardé Callback
mais je n'ai pas réussi à trouver un exemple simple pour comprendre comment l'utiliser.
Avez-vous un petit extrait de travail qui explique clairement comment et quand l'utiliser ?
Difficile à battre https://github.com/Moq/moq4/wiki/Quickstart
Si ce n'est pas assez clair, j'appellerais ça un bug doc...
EDIT : En réponse à votre précision...
Pour chaque méthode simulée Setup
vous vous produisez, vous pouvez indiquer des choses comme :
El .Callback
Le mécanisme dit : "Je ne peux pas le décrire pour l'instant, mais quand une forme d'appel comme celle-ci se produit, rappelez-moi et je ferai ce qui doit être fait". Dans le cadre de la même chaîne d'appel fluide, vous pouvez contrôler le résultat à renvoyer (s'il y en a un) par l'intermédiaire de .Returns
". Dans les exemples de QS, ils font en sorte que la valeur renvoyée augmente à chaque fois.
En général, vous n'aurez pas besoin d'un mécanisme comme celui-ci très souvent (les Test Patterns de xUnit ont des termes pour les anti-modèles de l'espèce Conditional Logic In Tests), et s'il existe un moyen plus simple ou intégré pour établir ce dont vous avez besoin, il devrait être utilisé de préférence.
Partie 3 sur 4 de la série Moq de Justin Etheredge le couvre, et il y a un autre exemple de callbacks ici
Un exemple simple de rappel se trouve à l'adresse suivante Utilisation de Callbacks avec Moq poste.
Bonjour Ruben, je suis en train d'apprendre Moq et si vous voulez, j'accumule beaucoup d'exemples pour comprendre comment faire les choses en l'utilisant. Mon problème est que je ne comprends pas quand l'utiliser. Une fois que j'aurai résolu ce problème, j'écrirai mon propre code. Si tu devais l'expliquer dans tes propres mots, quand utiliserais-tu le callback ? Merci d'avoir pris le temps de m'écouter.
Difficile à battre [lien] ? Pas du tout. Ce lien vous montre comment pour faire des dizaines de choses différentes, mais ne vous dit pas por qué dont vous auriez besoin pour les faire. C'est un problème courant dans la documentation sur les simulacres, j'ai trouvé. Je peux compter sur les doigts de la main le nombre de bonnes explications claires de TDD + mocking que j'ai trouvées. La plupart supposent un niveau de connaissance qui, si je l'avais, je n'aurais pas besoin de lire l'article.
@Kyralessa : Je comprends votre point de vue. Personnellement, j'avais déjà pas mal de connaissances livresques en arrivant et j'ai trouvé les trucs de démarrage rapide absolument parfaits. Malheureusement, je ne connais pas de meilleur exemple que ceux que j'ai mis en lien à la fin de l'article. Si vous en trouvez un, postez-le ici et je serai heureux de l'éditer (ou n'hésitez pas à faire du bricolage).
Voici un exemple d'utilisation d'un callback pour tester une entité envoyée à un service de données qui gère une insertion.
var mock = new Mock<IDataService>();
DataEntity insertedEntity = null;
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback((DataEntity de) => insertedEntity = de);
Syntaxe de la méthode générique alternative :
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback<DataEntity>(de => insertedEntity = de);
Vous pouvez alors tester quelque chose comme
Assert.AreEqual("test", insertedEntity.Description, "Wrong Description");
Dans ce cas particulier (selon que vous essayez d'exprimer des tests par rapport à l'état ou au comportement), il peut être plus propre d'utiliser un élément de type It.Is<T>
dans un Mock.Verify
au lieu de joncher le test de temps. Mais +1 parce que je parie qu'il y a beaucoup de gens qui travailleront mieux à partir d'un exemple.
Callback
est simplement un moyen d'exécuter le code personnalisé que vous souhaitez lorsqu'un appel est fait à l'une des méthodes de l'objet fantaisie. Voici un exemple simple :
public interface IFoo
{
int Bar(bool b);
}
var mock = new Mock<IFoo>();
mock.Setup(mc => mc.Bar(It.IsAny<bool>()))
.Callback<bool>(b => Console.WriteLine("Bar called with: " + b))
.Returns(42);
var ret = mock.Object.Bar(true);
Console.WriteLine("Result: " + ret);
// output:
// Bar called with: True
// Result: 42
J'ai récemment rencontré un cas d'utilisation intéressant. Supposons que vous attendez des appels à votre objet fantaisie, mais qu'ils se produisent simultanément. Vous n'avez donc aucun moyen de savoir dans quel ordre ils seront appelés, mais vous voulez savoir si les appels attendus ont bien eu lieu (indépendamment de l'ordre). Vous pouvez faire quelque chose comme ceci :
var cq = new ConcurrentQueue<bool>();
mock.Setup(f => f.Bar(It.IsAny<bool>())).Callback<bool>(cq.Enqueue);
Parallel.Invoke(() => mock.Object.Bar(true), () => mock.Object.Bar(false));
Console.WriteLine("Invocations: " + String.Join(", ", cq));
// output:
// Invocations: True, False
Ne vous laissez pas abuser par le terme trompeur "avant". Returns
"et "après Returns
distinction ". Il s'agit simplement d'une distinction technique qui permet de savoir si votre code personnalisé s'exécutera après l'entrée en vigueur de la loi. Returns
a été évalué ou avant. Aux yeux de l'appelant, les deux s'exécuteront avant que la valeur ne soit retournée. En effet, si la méthode est void
-Retourner vous ne pouvez même pas appeler Returns
et pourtant ça marche pareil. Pour plus d'informations, voir https://stackoverflow.com/a/28727099/67824 .
Il existe deux types de Callback
dans Moq. L'un se produit avant le retour de l'appel ; l'autre se produit après le retour de l'appel.
var message = "";
mock.Setup(foo => foo.Execute(arg1: "ping", arg2: "pong"))
.Callback((x, y) =>
{
message = "Rally on!";
Console.WriteLine($"args before returns {x} {y}");
})
.Returns(message) // Rally on!
.Callback((x, y) =>
{
message = "Rally over!";
Console.WriteLine("arg after returns {x} {y}");
});
Dans les deux callbacks, on peut :
En plus des autres bonnes réponses ici, je l'ai utilisé pour effectuer une logique avant de lancer une exception. Par exemple, j'avais besoin de stocker tous les objets qui étaient passés à une méthode pour une vérification ultérieure, et cette méthode (dans certains cas de test) devait lever une exception. Appeler .Throws(...)
en Mock.Setup(...)
remplace le Callback()
action et ne l'appelle jamais. Cependant, en lançant une exception dans la callback, vous pouvez toujours faire toutes les bonnes choses qu'une callback a à offrir, et toujours lancer une exception.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.