Testuję metodę usługi, która wykonuje API
połączenie internetowe . Używanie normalnego HttpClient
działa dobrze w testach jednostkowych, jeśli lokalnie uruchamiam również usługę internetową (znajdującą się w innym projekcie w rozwiązaniu).
Jednak po wpisaniu zmian serwer kompilacji nie będzie miał dostępu do usługi sieci Web, więc testy zakończą się niepowodzeniem.
Rozwiązałem ten problem w przypadku testów jednostkowych, tworząc IHttpClient
interfejs i implementując wersję używaną w mojej aplikacji. Do testów jednostkowych wykonuję próbną wersję z próbną metodą postu asynchronicznego. Tutaj napotkałem problemy. Chcę zwrócić OK HttpStatusResult
dla tego konkretnego testu. Do kolejnego podobnego testu zwrócę zły wynik.
Test zostanie uruchomiony, ale nigdy się nie zakończy. Wisi na oczekiwaniu. Jestem nowy w programowaniu asynchronicznym, delegatach i samym Moq i od dłuższego czasu szukam SO i Google, ucząc się nowych rzeczy, ale nadal nie mogę sobie poradzić z tym problemem.
Oto metoda, którą próbuję przetestować:
public async Task<bool> QueueNotificationAsync(IHttpClient client, Email email)
{
// do stuff
try
{
// The test hangs here, never returning
HttpResponseMessage response = await client.PostAsync(uri, content);
// more logic here
}
// more stuff
}
Oto moja metoda testu jednostkowego:
[TestMethod]
public async Task QueueNotificationAsync_Completes_With_ValidEmail()
{
Email email = new Email()
{
FromAddress = "[email protected]",
ToAddress = "[email protected]",
CCAddress = "[email protected]",
BCCAddress = "[email protected]",
Subject = "Hello",
Body = "Hello World."
};
var mockClient = new Mock<IHttpClient>();
mockClient.Setup(c => c.PostAsync(
It.IsAny<Uri>(),
It.IsAny<HttpContent>()
)).Returns(() => new Task<HttpResponseMessage>(() => new HttpResponseMessage(System.Net.HttpStatusCode.OK)));
bool result = await _notificationRequestService.QueueNotificationAsync(mockClient.Object, email);
Assert.IsTrue(result, "Queue failed.");
}
Co ja robię źle?
Dziękuję za pomoc
źródło
ReturnsAysnc
, które właśnie to robi.Polecam odpowiedź @Stuart Grassie powyżej.
źródło
Dzięki
Mock.Of<...>(...)
zaasync
metody można użyćTask.FromResult(...)
:źródło