【问题标题】:Silverlight async unit testingSilverlight 异步单元测试
【发布时间】:2012-07-15 20:07:40
【问题描述】:

我在使用 Silverlight 单元测试框架时遇到了一个奇怪的问题。每次执行的第一个方法都会失败。我用完全相同的代码进行了第二次测试,它通过了。第一次调用它的奇怪之处在于它实际上等待超时然后执行存储库调用(如果你关心的话,它下面是一个HTTP PUT)。这是代码 - 第一个每次都失败,第二个每次都通过:

    [TestMethod]
    public void AuthShouldSucceed()
    {
        var autoResetEvent = new AutoResetEvent(false);

        _authRepository.Authenticate(_username, _password, response =>
        {
            Assert.IsTrue(response);
            autoResetEvent.Set();
        });
        if (!autoResetEvent.WaitOne(Constants.Timeout))
        {
            Assert.Fail("Test timed out.");
        } 
    }

    [TestMethod]
    public void AuthShouldSucceed2()
    {
        var autoResetEvent = new AutoResetEvent(false);

        _authRepository.Authenticate(_username, _password, response =>
        {
            Assert.IsTrue(response);
            autoResetEvent.Set();
        });
        if (!autoResetEvent.WaitOne(Constants.Timeout))
        {
            Assert.Fail("Test timed out.");
        } 
    }

编辑: 我的最终解决方案是对 Vladmir 解决方案的修改:

    [TestMethod]
    [Asynchronous]
    public void AuthShouldSucceed()
    {
        var complete = false;
        var result = false;

        _authRepository.Authenticate(_username, _password, response =>
        {
            complete = true;
            result = response;
        });

        EnqueueConditional(() => complete);
        EnqueueCallback(() => Assert.IsTrue(result));
        EnqueueTestComplete();
    }

【问题讨论】:

    标签: silverlight unit-testing silverlight-toolkit silverlight-5.0


    【解决方案1】:

    总结所有编写的内容,您应该了解为 Silverlight 编写单元测试的几个要点。


    [Asynchronous]
    测试方法的属性表明您正在测试包含异步操作的部分,并希望同步它们以进行测试。 Silverlight 单元测试框架中的异步本身有点扭曲。所有的“入队”指令都类似于“推迟这个直到发生某些事情”,这不是传统编程异步含义所具有的意义。


    EnqueueConditional
    换句话说,就是等到条件满足。这是异步测试中最重要的部分之一。在条件变为合法后,所有EnqueueCallbacks 直到下一个EnqueueConditional 将被执行。

    Important note:

    EnqueueConditional 反复调用传递给它的谓词 定时器/后台线程,每次检查是否返回true。

    这就是为什么您应该避免在条件中使用繁重、复杂的逻辑。


    EnqueueCallback
    推迟代码执行直到满足条件的EnqueueConditional。它将ActoinActions 的数组排入队列。


    EnqueueDelay
    在继续之前将最小毫秒数/时间延迟排入队列。


    EnqueueTestComplete
    将调用 TestComplete 的操作排入队列,这表明使用异步测试时测试已完成。

    重要说明(来自文档):

    如果您使用自己的方法来完成,例如 HtmlTimer 或 其他线程方法,有可能会发生这个调用 AFTER 使用 Timeouts 时测试超时。因此,要非常小心,因为您可以完成对 next 测试的调用。

    【讨论】:

      【解决方案2】:

      如果您正在使用 Silverlight 单元测试框架,请尝试以下列方式重写您的测试:

          [TestMethod]
          [Asynchronous]
          public void AuthShouldSucceed()
          {
              var done = false;
              var authResult = false;
              _authRepository.Authenticate(_username, _password, response =>
              {
                  var done = true;
                  authResult = response;
              });
      
              EnqueueConditional(() => done);
              EnqueueCallback(() => Assert.IsTrue(authResult));
              EnqueueTestComplete();
          }
      

      您的测试类应该派生自 SilverlightTest 类:

      [TestClass]
      public class MyTests: SilverlightTest
      

      【讨论】:

      • 这太棒了,我要改变一件事。这是因为Authenticate 巧合地返回true。如果我正在测试 false 或者它返回了一些其他对象,它将无法工作。基本上,无论返回类型如何,我都修改了这个答案以使其正常工作 - 我使用了一个 done 变量,如上文建议的(以及结果变量)。
      【解决方案3】:

      可以在TestMethod中使用Asynchronous关键字

      [TestMethod]
      [Asynchronous]
      [Description("This test checks when NULL is passed")]
      
      public void Testing()
      {
       bool done = false;
       EnvViewModel test = new EnvViewModel ();
       .
       .
      
       test.AsyncCallBackCompleted += (() => done = true);
      
       EnqueueCallback(() => test.DataCommand.Execute(null));
       EnqueueConditional(() => done);
       EnqueueCallback(() => Assert.IsTrue(test.AADTDecisionModelList.Count == 0, 
                                                   "The result does not have any data."));
      
       EnqueueTestComplete();
      }
      

      并在 ViewModel 中创建一个委托,以用于正在测试的每个方法...

      public delegate void AsynCallComplete();
      public event AsynCallComplete AsyncCallBackCompleted;
      public void InformCallbackCompleted()
      {
           if (AsyncCallBackCompleted != null)
           {
                AsyncCallBackCompleted();
           }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-14
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多