Silverlight异步单元测试

时间:2012-07-16 22:20:04

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

我遇到了Silverlight Unit Test Framework的一个奇怪问题。每次执行的第一个方法都失败了。我用完全相同的代码进行了第二次测试,然后通过。第一次调用它时的奇怪之处在于它实际上等待超时然后执行存储库调用(如果你关心的话,它下面是一个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();
    }

3 个答案:

答案 0 :(得分:12)

如果您正在使用Silverlight Unit Tests Framework,请尝试下一步重写您的测试:

    [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

答案 1 :(得分:4)

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

<小时/> 的 [Asynchronous]
测试方法的属性表明您正在测试包含异步操作的部分,并希望将它们同步以用于测试目的。 Silverlight单元测试框架中的异步本身有点失真。所有“入队”指令都像是“推迟发生这种情况”,这不是传统编程异步意义所具有的意义。

<小时/> 的 EnqueueConditional
其他词表示等到满足条件。这是异步测试中最重要的部分之一。条件成为合法所有EnqueueCallbacks,直到下一个EnqueueConditional将被执行。

Important note:

  

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

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

<小时/> 的 EnqueueCallback
推迟代码执行,直到它前面的EnqueueConditional满足条件。它会将ActoinActions数组排成一列。

<小时/> EnqueueDelay
在继续之前排队最小毫秒数/时间延迟。

<小时/> 的 EnqueueTestComplete
TestComplete 的操作排入队列,这表示在使用异步测试时测试已完成。

重要说明(来自文档):

  

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

答案 2 :(得分: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();
     }
}