wpf - 集成测试在 WPF MVVM 应用程序中异步调用 WCF 服务的 ViewModel

标签 wpf mvvm asynchronous integration-testing

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 Extensions 的示例测试用例:

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

最佳答案

我一直在寻找这个功能,但不幸的是。

这不是一个真正干净的解决方案,但它对我有用。我通常使用 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();

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

最好的问候

关于wpf - 集成测试在 WPF MVVM 应用程序中异步调用 WCF 服务的 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3559554/

相关文章:

c# - WPF Caliburn.Micro/mvvm 导航

multithreading - TPL : Background thread completion notification?

wpf - 你如何在 .xaml 文件中使用 stylecop

c# - 将集合绑定(bind)到 WPF 列表框

c# - 使用 wpf 在列表框中绑定(bind)字典的键和值

android - new AsyncHttpResponseHandler() 总是会失败

android - 如何添加线程?

c# - 消息框弹出不止一次

c# - 这实际上如何重新排序列表中的项目?

c# - 使用 Async/Await 和 EntityFramework 调用多个存储过程