Xamarin 中的 NUnit 异步测试不起作用
Posted
技术标签:
【中文标题】Xamarin 中的 NUnit 异步测试不起作用【英文标题】:NUnit Async Testing in Xamarin Not Working 【发布时间】:2014-01-20 12:12:02 【问题描述】:我是 C# 世界的新手,正在尝试对 Xamarin 进行评估。我一直在做一个小型的web api库,到目前为止进展顺利,但是现在我正在尝试测试网络组件,我遇到了一些麻烦。
OS: OS X 10.9.1
Xamarin: 4.2.2 (build 2)
Library: PCL targeting 4.0 (Profile158)
Nunit target: Mono / .NET 4.5
类/方法:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
namespace LibTest
public class AsyncTest
public async Task<string> DoTest()
return await new HttpClient().GetStringAsync( "http://www.reddit.com/.json?limit=1" );
NUnit 测试类/案例:
using System;
using NUnit.Framework;
using LibTest;
namespace LibTestTests
[TestFixture]
public class LibTestTest
[Test]
public async void TempTest()
string data = await new AsyncTest().DoTest();
Assert.IsNotNull( data );
Assert.IsNull( data );
我的所有其他测试似乎都在工作(解析等),但这个测试只是通过了,就好像它通过了一样,但我不明白它是如何发生的,而且断言相互矛盾。
目前不支持此功能,还是我的实现不正确?
如果我使它与ContinueWith()
/ Wait()
同步,它会按预期工作,但显然我不想在我的库中重复实现,只是为了通过测试。
【问题讨论】:
【参考方案1】:NUnit 确实支持async Task
单元测试;不幸的是,Xamarin 使用的不是旧版本的 NUnit。但是,我不建议直接同步阻塞任务,因为这会使您的错误路径测试变得复杂(异常包含在 AggregateException
中)。
我的AsyncEx library 中有一个AsyncContext
类型,可以这样使用:
[Test]
public void TempTest()
AsyncContext.Run(async () =>
string data = await new AsyncTest().DoTest();
Assert.IsNotNull( data );
Assert.IsNull( data );
);
【讨论】:
太棒了,我同意阻塞不太理想,以后我在电脑上时肯定会检查那个库。 所以,我只能在使用异步 lambda 时编译和运行它,async () =>
,但随后我得到:Could not load type 'System.Object' from assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. I used Nuget to install
Nitro.AsyncEx, version
2.1.3`。
会不会是因为Nunit项目的目标框架是Mono / .NET 4.5
?
对不起;对于 ios 项目,您必须确保包含并编译了引用的 dll。我在这里没有很多经验,但是this question may help。【参考方案2】:
你有一个async void
方法。每当您使用它时,这应该是一个很大的危险信号。
一旦TempTest
击中第一个await
,它将返回给调用者。其余代码运行,但从调用者的角度来看,方法已经完成,调用者无法知道方法何时结束、它抛出的任何异常、任何失败的断言等。
当您同步等待时,您当然要确保异常是由调用此方法的线程引发的,而不是在测试框架无法观察到的其他地方的其他线程中引发的。
要正确测试异步方法,测试框架确实需要设计为支持它,真的。它应该能够处理返回Task
的方法,并根据Task
的结果采取行动。如果这不是一个选项,您将需要手动完成这项工作。理想情况下,为了保持适当的异步性,而不是等待任何任务,您应该设置自己的消息泵(参见here 示例),它将能够泵送消息直到***操作完成,从而允许您可以在同步方法中运行异步代码。
【讨论】:
谢谢,这很有道理。【参考方案3】:这里的操作顺序是:
-
NUnit 运行 TempTest()
TempTest 调用 new AsyncTest().DoTest(),它返回一个 Task
TempTest 的其余部分(断言)被安排为任务的延续
TempTest 方法返回 (void),NUnit 进入下一个测试
continuation 在未来某个时间点执行断言
由于没有观察到延续,断言失败异常未处理
您可能希望您的测试是同步的,并阻止您正在测试的异步事物的结果:
[Test]
public void TempTest()
string data = new AsyncTest().DoTest().Result;
Assert.IsNotNull( data );
Assert.IsNull( data );
【讨论】:
啊,这很有道理。虽然它并不理想,但我认为等待是保持库异步性的最佳选择。谢谢。以上是关于Xamarin 中的 NUnit 异步测试不起作用的主要内容,如果未能解决你的问题,请参考以下文章
nunit UITest xamarin.forms:如何滚动选择器?