使用起订量嘲笑为一个单元测试的异步方法 [英] Using Moq to mock an asynchronous method for a unit test
问题描述
我测试了,让一个Web API
呼叫服务的方法。使用普通的的HttpClient
工作正常进行单元测试,如果我还运行Web服务(位于另一个项目中的溶液)本地。
I am testing a method for a service that makes a Web API
call. Using a normal HttpClient
works fine for unit tests if I also run the web service (located in another project in the solution) locally.
然而,当我在变化检查构建服务器将无法访问该Web服务,以便测试将失败。
However when I check in my changes the build server won't have access to the web service so the tests will fail.
我想出解决的办法通过创建一个 IHttpClient
接口和实施,我在我的应用程序中使用的版本我的单元测试。单元测试,我做一个嘲笑完整版用嘲笑的异步POST方法。这里就是我所遇到的问题。我想返回一个OK HttpStatusResult
为这个特殊的测试。对于另一个类似的测试,我将返回一个坏的结果。
I've devised a way around this for my unit tests by creating an IHttpClient
interface and implementing a version that I use in my application. For unit tests, I make a mocked version complete with a mocked asynchronous post method. Here's where I have run into problems. I want to return an OK HttpStatusResult
for this particular test. For another similar test I will be returning a bad result.
该测试将运行,但将永远不会完成。它挂在游览车。我是新来的异步编程,委托和起订量本身,我一直很搜索和谷歌一段时间学习新的东西,但我似乎仍不能让过去这个问题。
The test will run but will never complete. It hangs at the await. I am new to asynchronous programming, delegates, and Moq itself and I've been searching SO and google for a while learning new things but I still can't seem to get past this problem.
下面是方法,我想测试一下:
Here is the method I am trying to test:
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
}
下面是我的单元测试方法:
Here's my unit test method:
[TestMethod]
public async Task QueueNotificationAsync_Completes_With_ValidEmail()
{
Email email = new Email()
{
FromAddress = "bob@example.com",
ToAddress = "bill@example.com",
CCAddress = "brian@example.com",
BCCAddress = "ben@example.com",
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.");
}
我在做什么错了?
What am I doing wrong?
感谢您的帮助。
推荐答案
您正在创建的任务,但从来没有启动它,所以它永远不会完成。但是,不要刚开始的任务 - 相反,改为使用<一个href=\"http://msdn.microsoft.com/en-us/library/hh194922%28v=vs.110%29.aspx\"><$c$c>Task.FromResult<TResult>$c$c>这将给你它已经完成的任务:
You're creating a task but never starting it, so it's never completing. However, don't just start the task - instead, change to using Task.FromResult<TResult>
which will give you a task which has already completed:
...
.Returns(Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK)));
请注意,你将不会被这种方式测试实际的异步 - 如果你想做到这一点,你需要做一些更多的工作,以创建一个任务&LT; T&GT;
,你可以在一个更精细的方式控制......但是这件事情的另一天。
Note that you won't be testing the actual asynchrony this way - if you want to do that, you need to do a bit more work to create a Task<T>
that you can control in a more fine-grained manner... but that's something for another day.
您可能还需要考虑使用一个假的 IHttpClient
,而不是嘲讽一切 - 这真的取决于你需要多久它
You might also want to consider using a fake for IHttpClient
rather than mocking everything - it really depends on how often you need it.
这篇关于使用起订量嘲笑为一个单元测试的异步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!