我正在尝试使用TouchRunner
测试第三方API IOS绑定(更像是集成测试)。
示例API方法就是这个 -
_client.AuthenticateWithUsername(username, token,
() => { // Success Callback },
() => { // NoConnection Callback },
(obj) => { // Other Error Callback });
API调用时关闭并在后台执行一些工作然后最终进行上面的一个回调,我想用类似的东西来控制单元测试的流程 -
How can I unit test async methods on the UI Thread with Xamarin iOS TouchRunner
不幸的是,当我插入AutoResetEvent
代码时,TouchRunner
只是挂起而永远不会返回到GUI。
我还尝试使用TaskCompletionSource
,如下所示 -
public async Task<AuthResponse> AuthenticateUserAsync(string username, string password)
{
TaskCompletionSource<AuthResponse> tcs = new TaskCompletionSource<AuthResponse>();
AuthResponse response = new AuthResponse { Success = false };
LoginResponse loginResponse = await LoginUser(username, password);
_client.AuthenticateWithUsername(username, loginResponse.token,
() =>
{
response.Success = true;
Console.WriteLine("Auth");
tcs.SetResult(response);
},
() => { tcs.SetResult(response); },
obj => { tcs.SetResult(response); },
obj => { tcs.SetResult(response); });
return await tcs.Task;
}
[Test]
public async void AuthenticateUserAsyncTest()
{
var auth = await AuthenticateUserAsync(_username, _password);
Assert.IsTrue(auth.Success);
}
调试器逐步完成,直到返回等待tcs.Task
,然后导致类似的HUNG运行器。
我怎样才能弄清楚为什么会发生这种情况?
由于这不起作用,我接着使用这样的代码 -
_client.AuthenticateWithUsername(_username, loginResponse.token,
() =>
{
Assert.Pass("This crashes the runner");
Assert.True(true); // This DOES NOT!
},
() =>
{
// This will crash runner also
Assert.Fail("NoConnection");
},
(InvalidTokenError obj) =>
{
Assert.Fail("InvalidToken" + obj.Description);
},
(ClientError obj) =>
{
Assert.Fail("ClientError" + obj.Description);
});
正如您所看到的,流程最终(可理解),运行测试,运行客户端调用,测试结束方法完成,显示测试成功,然后回调返回并且断言被调用,这使应用程序崩溃,我们假设是因为跑步者已经完成了测试,为什么一个断言工作和其他我不知道的崩溃。
所以,
答案 0 :(得分:1)
感谢@Nkosi,这是一个很好的建议,我忘了在原始测试期间添加,当我使用异步任务运行代码而不是无效时,我从TouchRunner立即阻止,甚至没有添加任何其他代码API调用!我想这是一个红旗,但使用async void&#34;似乎&#34;允许&#34;标准&#34;异步测试,所以我继续进行,然后在上面的循环中结束。
由于TouchRunner在很长一段时间内没有更新,我花了很多时间在论坛和堆栈中尝试使用XUnit重新创建测试项目。
其他一些有用的链接是 -
结果:我很高兴地说上述代码现在适用于TaskCompletionSource和AutoResetTask场景
我现在可以安全地测试基于事件的API:)
我只想确保其他用户了解这一点。 谢谢你的帮助。
答案 1 :(得分:0)
一个观察结果是测试应该是async Task
而不是async void
即
public async Task AuthenticateUserAsyncTest() {
//...code removed for brevity.
}
async void是一个火,忘记所以抛出的任何异常都不会在当前上下文中发生,所以它们不会被捕获。