Xamarin TouchRunner挂起呼叫IOS第三方绑定

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xamarin TouchRunner挂起呼叫IOS第三方绑定相关的知识,希望对你有一定的参考价值。

我有一个第三方API ios绑定,我试图使用TouchRunner测试(更像是集成测试)。

一个示例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);
     });

正如您所看到的,流程最终(可理解),运行测试,运行客户端调用,测试结束方法完成,显示测试成功,然后回调返回并且断言被调用,这使应用程序崩溃,我们假设是因为跑步者已经完成了测试,为什么一个断言工作和其他我不知道的崩溃。

所以,

  • 我是以正确的方式接近这个吗?
  • 可能会在第三方API中发生导致这些方法挂起的事情吗?我该如何调试呢?
答案

谢谢@Nkosi,这是一个很好的建议,我忘了在原始测试期间添加,当我使用异步任务运行代码而不是无效时,我从TouchRunner立即阻止,甚至没有添加除API调用之外的任何其他代码!我认为这是一个红旗,但使用async void“似乎”允许“标准”异步测试,所以我继续进行,然后在上面的循环中结束。

由于TouchRunner在很长一段时间内没有更新,我花了很多时间在论坛和堆栈中尝试各种建议之后使用XUnit重新创建测试项目。

其他一些有用的链接是 -

结果:我很高兴地说上面的所有代码现在都适用于TaskCompletionSource和AutoResetTask场景

我现在可以安全地测试基于事件的API :)

我只是想确保其他用户都知道这一点。谢谢你的帮助。

另一答案

一个观察是测试应该是async Task而不是async void

public async Task AuthenticateUserAsyncTest() {
    //...code removed for brevity.
}

async void是一个火,忘记所以抛出的任何异常都不会在当前上下文中发生,因此它们不会被捕获。

参考Async/Await - Best Practices in Asynchronous Programming

以上是关于Xamarin TouchRunner挂起呼叫IOS第三方绑定的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 形成 UWP 缺少电话呼叫管理器程序集

Xamarin.Mac 应用程序在与最终用户的文件系统交互时挂起

xamarin forms ios release build 挂起

从 Xamarin PCL 调用 REST API 时程序挂起

MvvmCross Xamarin Android 在初始屏幕上挂起并带有链接

执行任何 IO/流时 C++ JNI 崩溃/挂起