Estou testando um método para um serviço que faz uma API
chamada pela Web . Usar um normal HttpClient
funciona bem para testes de unidade, se eu também executar o serviço da Web (localizado em outro projeto na solução) localmente.
No entanto, ao fazer o check-in de minhas alterações, o servidor de compilação não terá acesso ao serviço da web, portanto os testes falharão.
Eu criei uma maneira de contornar isso para meus testes de unidade, criando uma IHttpClient
interface e implementando uma versão que eu uso no meu aplicativo. Para testes de unidade, faço uma versão simulada completa com um método de postagem assíncrona simulada. Aqui é onde eu encontrei problemas. Eu quero retornar um OK HttpStatusResult
para este teste específico. Para outro teste semelhante, retornarei um resultado ruim.
O teste será executado, mas nunca será concluído. Trava na espera. Eu sou novo na programação assíncrona, delegados e no próprio Moq e tenho pesquisado o SO e o Google por um tempo aprendendo coisas novas, mas ainda não consigo superar esse problema.
Aqui está o método que estou tentando testar:
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
}
Aqui está o meu método de teste de unidade:
[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.");
}
O que estou fazendo de errado?
Obrigado pela ajuda.
fonte
ReturnsAysnc
, que faz exatamente isso.Recomende a resposta de @Stuart Grassie acima.
fonte
Com
Mock.Of<...>(...)
aasync
método que pode utilizarTask.FromResult(...)
:fonte