3

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

3 回答 3

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

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

[TestClass]
public class MyTests: SilverlightTest
于 2012-07-19T08:11:25.377 回答
4

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


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


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

重要的提示:

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

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


EnqueueCallback
推迟代码执行,直到EnqueueConditional它满足条件。Actoin它将一个或一个数组排入队列Actions


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


EnqueueTestComplete
在使用异步测试时,将要调用的动作排入队列,该动作TestComplete表示测试已完成。

重要说明(来自文档):

如果您使用自己的方法来完成,例如 HtmlTimer 或其他线程方法,则 在使用 Timeouts 时测试超时后可能会发生此调用。因此,请非常小心,因为您可以完成对下一个测试的调用。

于 2012-07-19T22:46:23.187 回答
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();
     }
}
于 2012-07-19T08:15:15.950 回答