【问题标题】:Integration Testing a ViewModel that calls WCF Services asynchronously in a WPF MVVM Application集成测试在 WPF MVVM 应用程序中异步调用 WCF 服务的 ViewModel
【发布时间】:2010-08-24 18:05:59
【问题描述】:

Silverlight 工具包包含单元测试功能,允许测试类,例如异步调用远程服务的 MVVM 应用程序中的 ViewModel。

我希望能够针对实际服务而不是模拟实例执行我的 ViewModel 集成测试。

是否支持 WPF 应用程序的异步单元/集成测试?

更新:

最终,我的解决方案结合了 ktutnik 和 Alex Paven 的建议。我写了一个小助手类,添加了一些语法糖:

public static class AsyncMethod
{
    public delegate void AsyncMethodCallback(AsyncMethodContext ctx);

    public static void Call(AsyncMethodCallback cb)
    {
        // create the sync object and make it available via TLS
        using (var syncObject = new AutoResetEvent(false))
        {
            // call the decorated method
            cb(new AsyncMethodContext(syncObject));
        }
    }
}

/// <summary>Asnc Method Callback Synchronization Context</summary>
public class AsyncMethodContext
{
    public AsyncMethodContext(EventWaitHandle syncObject)
    {
        this.syncObject = syncObject;
    }

    private readonly EventWaitHandle syncObject;

    /// <summary>
    /// Waits for completion.
    /// </summary>
    public void WaitForCompletion()
    {
        syncObject.WaitOne();
    }

    /// <summary>
    /// Signals the current operation as complete
    /// </summary>
    public void Complete()
    {
        syncObject.Set();
    }
}

这是一个示例测试用例,结合了 Microsoft Rx 扩展的使用:

[TestMethod]
public void TestGuestLogin()
{
    AsyncMethod.Call((ctx) =>
    {
        var vm = ServiceLocator.Get<LoginDialogViewModel>();

        // setup VM data
        vm.Username = "guest";
        vm.Password = "guest";
        vm.AutoLogin = false;
        GenericInfoEventArgs<LoginDialogViewModel.LoginRequestResult> loginResult = null;

        // pre-flight check
        Assert.IsTrue(vm.LoginCmd.CanExecute(null));

        // create Observable for the VM's LoginRequestComplete event
        var loginEvent = Observable.FromEvent<GenericInfoEventArgs<LoginDialogViewModel.LoginRequestResult>>(vm, "LoginRequestComplete").Do((e) =>
        {
            Debug.WriteLine(e.ToString());
        });

        // subscribe to it
        var loginEventSubscription = loginEvent.Subscribe((e) =>
        {
            loginResult = e.EventArgs;

            // test complete
            ctx.Complete();
        });

        // set things in motion
        using (loginEventSubscription)
        {
            vm.LoginCmd.Execute(null);
            ctx.WaitForCompletion();

            Assert.IsTrue(loginResult.Info.Success, "Login was not successful");
        }
    });
}

【问题讨论】:

    标签: wpf mvvm asynchronous integration-testing


    【解决方案1】:

    我一直在寻找这个功能,但运气不好。

    不是一个真正干净的解决方案,但它对我有用。我通常使用ManualResetEvent,所以在异步完成之前测试过程不会失败。思路如下:

    //set false for initial state
    resetEvent = new ManualResetEvent(false);
    //do the test
    myObjec.MakeMeHappyAssync();
    //just wait until its state set 
    //when your call done
    resetEvent.WaitOne();
    //do assertion here
    

    您只需调用 Complete Method 或 Fault Method 中的某处

    resetEvent.Set();
    

    如果您发现有关该功能的任何新信息,请告诉我

    最好的问候

    【讨论】:

    • 不幸的是,这就是我的解决方案最终归结为的内容。查看我更新的帖子。
    【解决方案2】:

    假设您正在使用它,您可以查看现在包含在 .Net Framework 4 中的 Reactive Extensions;还有 3.5 和 Silverlight 的版本。它们允许一些不错的异步编码,我以前在单元测试中使用过它们。请参阅 here 以获取讨论它的博客文章。

    【讨论】:

    • 很好的建议。阅读和使用该库真的让人大开眼界。
    猜你喜欢
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 2015-02-19
    • 1970-01-01
    相关资源
    最近更新 更多