3

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

[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."); 
     } 
    } 

编辑: 我的最终解决方案是弗拉基米尔·解决方案的修改:

[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(); 
    } 

回答

12

如果你使用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(); 
    } 

您的测试类应该从S ilverlightTest类:

[TestClass] 
public class MyTests: SilverlightTest 
+0

这真棒,我会改变一件事。这是有效的,因为'Authenticate'巧合地返回'true'。如果我正在测试'false'或者返回了一些其他对象,它将无法工作。基本上我修改了这个答案,无论返回类型如何 - 我使用了一个像上面提到的一样的'done'变量(以及结果变量)。 – user140550 2012-07-19 20:46:36

+0

当然,你是对的,适当地更新答案 – 2012-07-19 20:53:02

3

可以使用异步关键字在TestMethod的

[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(); 
} 

并做好代表在视图模型中使用的每一个被测试方法...

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

总结所有书面你应该知道在编写Silverlight单元测试中的几个要点。


[Asynchronous]
属性测试方法表明,你正在测试,其中包括异步操作,并希望他们syncronize用于测试目的的一部分。 Silverlight单元测试框架中的异步本身有点失真。所有的“Enqueue”指令都像“推迟到事情发生时”,这不是传统编程异步含义所具有的意义。


EnqueueConditional
Otherwords手段等到条件将得到满足。这是异步测试最重要的部分之一。条件成为合法后,全部 EnqueueCallbacks,直到下一个 EnqueueConditional将被执行。

Important note:

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

这就是为什么你应该避免在条件下使用沉重,复杂的逻辑。


EnqueueCallback
推迟执行代码,直到 EnqueueConditional它前面将满足条件。它排入 Actoin或排列 Actions


EnqueueDelay
排入毫秒继续前/延迟时间的最小数量。


EnqueueTestComplete
排入一个动作来调用 TestComplete这标志着试验使用异步测试完成时。

重要事项(来自文件):

如果您使用自己完成,比如HtmlTimer或 其它线程的方法方法,有可能是这个调用会发生 使用超时时,测试已超时。因此,要非常小心,因为您可以完成对下一个测试的呼叫。