MVVM单元测试-消息总线仅工作一次 [英] MVVM unit tests - message bus only works once

查看:58
本文介绍了MVVM单元测试-消息总线仅工作一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用SimpleMvvmToolkit针对视图模型编写一些单元测试,其中一些测试需要将消息发送到消息总线以激发视图模型内部的事件.问题在于,我只能使用"消息总线一次;发送消息的第一个测试通过,但是发送消息的其他两个测试失败.但是,如果我分别运行每个测试,则所有三个测试都通过了;如果更改顺序,则第一个测试(无论是哪个测试)都将通过.

I am trying to write some unit tests against a view model using SimpleMvvmToolkit, and several of these tests require a message be sent to the message bus to fire events inside the view model. The problem is it appears that I can only 'use' the message bus once; the first test that sends a message passes, but the other two that send a message fail. But if I run each test individually, all three pass, and if I change the order, the first test, no matter which one it is, passes.

这里是其中一项测试的样本.

Here is a sample of one of the tests.

[TestMethod]
public void DeleteRequest()
{
    // mock the driver transaction service

    var driverTransactionService =
         new Mock<Services.IDriverTransactionService>();

    var viewModel = new ValidationRequestViewModel(
         driverTransactionService.Object);

    driverTransactionService.Setup(dts =>
         dts.DeleteValidationRequest(It.IsAny<Action<int>>(), 
              It.IsAny<Action<Exception>>(),
              It.IsAny<int>()))
        .Callback((Action<int> action, Action<Exception> ex, int id) => 
             action.Invoke(requestId));

    // make a validation request and add to the collection

    var validationRequest = new ValidationRequest...

    var collection = viewModel.ValidationRequestView.SourceCollection as 
         ObservableCollection<ValidationRequest>;

    collection.Add(validationRequest);

    //  delete the validation request; send the confirmation message as if
    //  the user clicked yes

    viewModel.DeleteValidationRequest(validationRequest);

    MessageBus.Default.Notify(
         NotificationMessages.DeleteValidationRequestConfirmation, 
         this, new NotificationEventArgs<String>(null, null));

    // verify the service call was made

    driverTransactionService.Verify(dts => 
         dts.DeleteValidationRequest(It.IsAny<Action<int>>(), 
              It.IsAny<Action<Exception>>(), requestId));
}

因此,我正在创建服务的模拟(它是WCF服务的包装),并验证是否正在调用该服务上的DeleteValidatonRequest.在这种情况下,需要消息总线,因为如果用户单击确定",通常会弹出确认对话框并发送DeleteValidationRequestConfirmation消息.

So I am creating a mock of a service (which is a wrapper around a WCF service) and verifying that DeleteValidatonRequest on the service is being called. In this case, the message bus is needed because a confirmation dialog would normally pop up and send the DeleteValidationRequestConfirmation message if the user clicks OK.

测试在最后一行(Verify)失败,并且在我调试时,视图模型中消息的处理程序永远不会执行,因此看起来消息从未真正发送过.同样,只有在测试不是不是第一个向总线发送消息的测试时,测试才会失败.如果它是单独执行还是第一次执行,则测试通过.

The test fails on the last line (Verify) and when I debug, the handler for the message in the view model never executes so it looks like the message is never actually sent. Again, this only fails if the test is not the first test to send a message to the bus. If it executes alone or is the first, the test passes.

有什么想法吗?所有测试都是独立的,并且不共享测试类的任何属性或变量,因此我看不到它们之间如何相互影响.

Any ideas? All of the tests are independent and do not share any properties or variables of the test class so I don't see how they could be stepping on each other.

我使用反射在消息通常会触发的视图模型上调用受保护的方法;这可以获取所需的代码覆盖率,只是无法验证视图模型是否正确响应了消息.

I used reflection to call the protected methods on the view model that the messages would normally fire; this gets me the code coverage I want, it just doesn't verify that the view model is responding to messages correctly.

糟糕,视图模型上的PropertyChanged事件也发生了同样的事情.仅当测试是独立运行还是第一次运行时,事件处理程序才会触发.

EDIT 2: Crap, the same thing is happening with PropertyChanged events on the view model. The event handler only fires if the test is run independently or is the first.

推荐答案

我不熟悉SimpleMvvmToolkit,但是我熟悉消息传递的概念.

I'm not familiar with SimpleMvvmToolkit, but I am familiar with the concept of messaging.

请勿使用MessageBus.Default.将ViewModel修改为具有MessageBusIMessageBus(如果存在)构造函数参数.现在,您的测试将被隔离,因此您可以一次运行所有测试,它们应该通过.

Don't use MessageBus.Default. Modify your ViewModels to have a MessageBus, or IMessageBus if it exists, constructor parameter. Now your tests will be isolated, so you can run them all at once and they should pass.

此外,如果存在IMessageBus接口,则可以模拟它,这将使测试ViewModel更加容易.

Additionally, if the IMessageBus interface exists, you can Mock it, which should make it even easier to test your ViewModels.

这篇关于MVVM单元测试-消息总线仅工作一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆