单元测试异步方法-测试永远不会完成 [英] Unit testing async method - test never completes
问题描述
我正在尝试对正在构建的类进行单元测试,该类将调用许多URL(异步)并检索其内容.
I'm trying to unit test my a class I'm building that calls a number of URLs (Async) and retrieves the contents.
这是我遇到问题的测试:
Here's the test I'm having a problem with:
[Test]
public void downloads_content_for_each_url()
{
_mockGetContentUrls.Setup(x => x.GetAll())
.Returns(new[] { "http://www.url1.com", "http://www.url2.com" });
_mockDownloadContent.Setup(x => x.DownloadContentFromUrlAsync(It.IsAny<string>()))
.Returns(new Task<IEnumerable<MobileContent>>(() => new List<MobileContent>()));
var downloadAndStoreContent= new DownloadAndStoreContent(
_mockGetContentUrls.Object, _mockDownloadContent.Object);
downloadAndStoreContent.DownloadAndStore();
_mockDownloadContent.Verify(x => x.DownloadContentFromUrlAsync("http://www.url1.com"));
_mockDownloadContent.Verify(x => x.DownloadContentFromUrlAsync("http://www.url2.com"));
}
DownloadContent
的相关部分是:
public void DownloadAndStore()
{
//service passed in through ctor
var urls = _getContentUrls.GetAll();
var content = DownloadAll(urls)
.Result;
//do stuff with content here
}
private async Task<IEnumerable<MobileContent>> DownloadAll(IEnumerable<string> urls)
{
var list = new List<MobileContent>();
foreach (var url in urls)
{
var content = await _downloadMobileContent.DownloadContentFromUrlAsync(url);
list.AddRange(content);
}
return list;
}
运行测试时,它永远不会完成-只是挂起.
When my test runs, it never completes - it just hangs.
我怀疑应该怪我的 _mockDownloadContent
设置中的某件事...
I suspect something in the setup of my _mockDownloadContent
is to blame...
推荐答案
您的问题出在此模拟游戏中:
Your problem is in this mock:
new Task<IEnumerable<MobileContent>>(() => new List<MobileContent>())
您不应在异步代码中使用 Task
构造函数.而是使用 Task.FromResult
:
You should not use the Task
constructor in asynchronous code. Instead, use Task.FromResult
:
Task.FromResult<IEnumerable<MobileContent>>(new List<MobileContent>())
我建议您阅读我的 MSDN文章或
I recommend you read my MSDN article or async
blog post which point out that the Task
constructor should not be used for async
code.
此外,我建议您采纳Servy的建议并一直"进行异步(这在我的MSDN文章中也已有介绍).如果您正确使用 await
,则您的代码将更改为如下所示:
Also, I recommend you do take Servy's advice and do async "all the way" (this is also covered by my MSDN article). If you use await
properly, your code would change to look like this:
public async Task DownloadAndStoreAsync()
{
//service passed in through ctor
var urls = _getContentUrls.GetAll();
var content = await DownloadAllAsync(urls);
//do stuff with content here
}
您的测试如下:
[Test]
public async Task downloads_content_for_each_url()
{
_mockGetContentUrls.Setup(x => x.GetAll())
.Returns(new[] { "http://www.url1.com", "http://www.url2.com" });
_mockDownloadContent.Setup(x => x.DownloadContentFromUrlAsync(It.IsAny<string>()))
.Returns(Task.FromResult<IEnumerable<MobileContent>>(new List<MobileContent>()));
var downloadAndStoreContent= new DownloadAndStoreContent(
_mockGetContentUrls.Object, _mockDownloadContent.Object);
await downloadAndStoreContent.DownloadAndStoreAsync();
_mockDownloadContent.Verify(x => x.DownloadContentFromUrlAsync("http://www.url1.com"));
_mockDownloadContent.Verify(x => x.DownloadContentFromUrlAsync("http://www.url2.com"));
}
请注意,现代版本的NUnit可以理解 async Task
单元测试,而不会出现任何问题.
Note that modern versions of NUnit understand async Task
unit tests without any problems.
这篇关于单元测试异步方法-测试永远不会完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!