J'ai une interface qui déclare
Task DoSomethingAsync();
J'utilise MoqFramework pour mes tests:
[TestMethod()]
public async Task MyAsyncTest()
{
Mock<ISomeInterface> mock = new Mock<ISomeInterface>();
mock.Setup(arg => arg.DoSomethingAsync()).Callback(() => { <my code here> });
...
}
Ensuite, dans mon test, j'exécute le code qui appelle await DoSomethingAsync()
. Et le test échoue simplement sur cette ligne. Qu'est-ce que je fais mal?
Votre méthode n'a aucun rappel, il n'y a donc aucune raison d'utiliser .CallBack()
. Vous pouvez simplement renvoyer une tâche avec les valeurs souhaitées en utilisant .Returns()
et Task.FromResult , par exemple:
MyType someValue=...;
mock.Setup(arg=>arg.DoSomethingAsync())
.Returns(Task.FromResult(someValue));
Mise à jour du 2014-06-22
Moq 4.2 dispose de deux nouvelles méthodes d'extension pour vous aider.
mock.Setup(arg=>arg.DoSomethingAsync())
.ReturnsAsync(someValue);
mock.Setup(arg=>arg.DoSomethingAsync())
.ThrowsAsync(new InvalidOperationException());
Mise à jour 2016-05-05
Comme Seth Flowers le mentionne dans le autre réponse , ReturnsAsync
n'est disponible que pour les méthodes qui renvoient un Task<T>
. Pour les méthodes qui ne renvoient qu'une tâche,
.Returns(Task.FromResult(default(object)))
peut être utilisé.
Comme indiqué dans cette réponse , dans .NET 4.6, ceci est simplifié en .Returns(Task.CompletedTask);
, par exemple:
mock.Setup(arg=>arg.DoSomethingAsync())
.Returns(Task.CompletedTask);
Problème similaire
J'ai une interface qui ressemble à peu près à:
Task DoSomething(int arg);
Symptômes
Mon test unitaire a échoué lorsque mon service en cours de test awaited
l'appel à DoSomething
.
Fix
Contrairement à la réponse acceptée, vous ne pouvez pas appeler .ReturnsAsync()
sur votre Setup()
de cette méthode dans ce scénario, car la méthode renvoie le Task
non générique, plutôt que Task<T>
. .
Cependant, vous pouvez toujours utiliser .Returns(Task.FromResult(default(object)))
sur la configuration, permettant ainsi au test de réussir.
Il vous suffit d'ajouter .Returns(Task.FromResult(0));
après le rappel.
Exemple:
mock.Setup(arg => arg.DoSomethingAsync())
.Callback(() => { <my code here> })
.Returns(Task.FromResult(0));
Maintenant, vous pouvez également utiliser le package Talentsoft.Moq.SetupAsync https://github.com/TalentSoft/Moq.SetupAsync
Sur la base des réponses trouvées ici et des idées proposées à Moq mais non encore implémentées ici: https://github.com/moq/moq4/issues/384 , simplifie grandement la configuration des méthodes asynchrones
Quelques exemples trouvés dans les réponses précédentes effectuées avec l'extension SetupAsync:
mock.SetupAsync(arg=>arg.DoSomethingAsync());
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Callback(() => { <my code here> });
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Throws(new InvalidOperationException());