Ich habe eine Schnittstelle, die deklariert
Task DoSomethingAsync();
Ich benutze MoqFramework für meine Tests:
[TestMethod()]
public async Task MyAsyncTest()
{
Mock<ISomeInterface> mock = new Mock<ISomeInterface>();
mock.Setup(arg => arg.DoSomethingAsync()).Callback(() => { <my code here> });
...
}
Dann führe ich in meinem Test den Code aus, der await DoSomethingAsync()
aufruft. Und der Test schlägt in dieser Zeile einfach fehl. Was mache ich falsch?
Ihre Methode hat keine Rückrufe, daher gibt es keinen Grund, .CallBack()
zu verwenden. Sie können einfach eine Aufgabe mit den gewünschten Werten zurückgeben, indem Sie .Returns()
und Task.FromResult verwenden, z.
MyType someValue=...;
mock.Setup(arg=>arg.DoSomethingAsync())
.Returns(Task.FromResult(someValue));
Update 22.06.2014
Moq 4.2 hat zwei neue Erweiterungsmethoden, um dies zu unterstützen.
mock.Setup(arg=>arg.DoSomethingAsync())
.ReturnsAsync(someValue);
mock.Setup(arg=>arg.DoSomethingAsync())
.ThrowsAsync(new InvalidOperationException());
Update 05.05.2016
Wie Seth Flowers in andere Antwort erwähnt, ist ReturnsAsync
nur für Methoden verfügbar, die einen Task<T>
Zurückgeben. Für Methoden, die nur eine Aufgabe zurückgeben,
.Returns(Task.FromResult(default(object)))
kann verwendet werden.
Wie in diese Antwort gezeigt, wird dies in .NET 4.6 zu .Returns(Task.CompletedTask);
vereinfacht, z.
mock.Setup(arg=>arg.DoSomethingAsync())
.Returns(Task.CompletedTask);
Ähnliches Problem
Ich habe eine Oberfläche, die ungefähr so aussah:
Task DoSomething(int arg);
Symptome
Mein Komponententest ist fehlgeschlagen, als mein zu testender Dienst awaited
den Aufruf von DoSomething
ausführte.
Fix
Anders als bei der akzeptierten Antwort können Sie in diesem Szenario .ReturnsAsync()
für Ihre Setup()
dieser Methode nicht aufrufen, da die Methode nicht generisch Task
zurückgibt, sondern Task<T>
.
Sie können jedoch weiterhin .Returns(Task.FromResult(default(object)))
für das Setup verwenden, damit der Test bestanden werden kann.
Sie müssen nur .Returns(Task.FromResult(0));
nach dem Rückruf hinzufügen.
Beispiel:
mock.Setup(arg => arg.DoSomethingAsync())
.Callback(() => { <my code here> })
.Returns(Task.FromResult(0));
Jetzt können Sie auch das Talentsoft.Moq.SetupAsync-Paket https://github.com/TalentSoft/Moq.SetupAsync verwenden.
Was auf der Basis der hier gefundenen Antworten und hier noch nicht umgesetzten Ideen an Moq geht: https://github.com/moq/moq4/issues/384 , vereinfacht die Einrichtung von asynchronen Methoden erheblich
Einige Beispiele aus früheren Antworten mit der SetupAsync-Erweiterung:
mock.SetupAsync(arg=>arg.DoSomethingAsync());
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Callback(() => { <my code here> });
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Throws(new InvalidOperationException());