0

我正在尝试使用 SimpleMvvmToolkit 针对视图模型编写一些单元测试,其中一些测试需要将消息发送到消息总线以触发视图模型内的事件。问题是我似乎只能“使用”一次消息总线;发送消息的第一个测试通过,但发送消息的另外两个测试失败。但是如果我单独运行每个测试,所有三个都通过,如果我改变顺序,第一个测试,无论是哪一个,都会通过。

这是其中一项测试的示例。

[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 消息。

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

有任何想法吗?所有测试都是独立的,并且不共享测试类的任何属性或变量,所以我看不出它们如何相互踩踏。

编辑:我使用反射调用消息通常会触发的视图模型上的受保护方法;这得到了我想要的代码覆盖率,它只是没有验证视图模型是否正确响应消息。

编辑 2:废话,视图模型上的 PropertyChanged 事件也发生了同样的事情。事件处理程序仅在测试独立运行或第一个运行时触发。

4

1 回答 1

3

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

不要使用MessageBus.Default. 修改您的 ViewModel 以具有构造函数参数MessageBus,或者IMessageBus如果存在,构造函数参数。现在您的测试将被隔离,因此您可以一次运行它们并且它们应该通过。

此外,如果IMessageBus接口存在,您可以对其进行 Mock,这将使您的 ViewModel 测试变得更加容易。

于 2012-08-16T17:16:57.910 回答