【问题标题】:Using Moq to verify a Prism event subscription fails使用 Moq 验证 Prism 事件订阅失败
【发布时间】:2014-01-09 07:34:54
【问题描述】:

我将 Prism 框架与 Moq 一起使用。我正在尝试验证 AlarmService 是否订阅了构造函数中的事件,但我收到了一个不支持的异常。

我还能如何验证这一点?

这是我的测试方法:

public void TestMethod()
{
    var mockMachineDataService = new Mock<IMachineDataService<AlarmDto>>();
    var mockAggregator = new Mock<IEventAggregator>();
    var mockEvent = new Mock<MachineMessageReceivedEvent>();
    mockAggregator.Setup(x => x.GetEvent<MachineMessageReceivedEvent>()).Returns(mockEvent.Object);

    var alarmService = new AlarmService(mockAggregator.Object, mockMachineDataService.Object);
    Assert.IsNotNull(alarmService);

    mockAggregator.VerifyAll();
    mockEvent.Verify(x => x.Subscribe(It.IsAny<Action<MachineMessage>>(), It.IsAny<ThreadOption>()));
}

当我运行它时,我得到以下失败:

System.NotSupportedException: Invalid verify on a non-virtual (overridable in VB) member: x => x.Subscribe(It.IsAny<Action`1>(), It.IsAny<ThreadOption>())

我确实查看了this 并将mockAggregator 和mockEvent 分开以获得上述代码,但它仍然失败。

【问题讨论】:

    标签: c# moq prism


    【解决方案1】:

    我猜问题是订阅方法被重载,最后调用了另一个订阅方法,它有更多的默认选项是虚拟的。通过更改测试来验证这个虚拟方法,我可以验证订阅方法是否已被调用。

    [TestMethod]
    public void TestConstructorSubscribesToMachineMessages()
    {
        var mockMachineDataService = new Mock<IMachineDataService<AlarmDto>>();
        var mockAggregator = new Mock<IEventAggregator>();
        var mockEvent = new Mock<MachineMessageReceivedEvent>();
        mockAggregator.Setup(x => x.GetEvent<MachineMessageReceivedEvent>()).Returns(mockEvent.Object);
        mockEvent.Setup(x => x.Subscribe(It.IsAny<Action<MachineMessage>>(), It.IsAny<ThreadOption>(), It.IsAny<bool>(), It.IsAny<Predicate<MachineMessage>>()));
    
        var alarmService = new AlarmService(mockAggregator.Object, mockMachineDataService.Object);
        Assert.IsNotNull(alarmService);
    
        mockAggregator.VerifyAll();
        mockEvent.VerifyAll();
    }
    

    【讨论】:

      【解决方案2】:

      您只能模拟/验证虚拟或接口方法。看起来Subscribe 不是虚拟方法。

      Moq(和少数其他框架)使用 Castle Project 的 DynamicProxy 在运行时动态生成代理,以便在不修改类代码的情况下拦截对象的成员。这种拦截只能在公共虚拟和受保护的虚拟方法上完成。

      更多信息请见以下网址:http://www.castleproject.org/projects/dynamicproxy/

      更新:对于您无法修改的代码,您可以使用 Microsoft Fakes 框架提供的 Shims。注意:将 Shims 用于您自己的代码并不是一个好习惯。

      http://msdn.microsoft.com/en-us/library/hh549175.aspx

      How can I verify that a Microsoft Fakes (beta) stub/shim was called (like AssertWasCalled in Rhino Mocks)?

      【讨论】:

      • 确实不是虚的,让我困惑的是Unsubscribe方法是虚的而Subscribe方法不是。
      • 谢谢,我添加了一个可行的解决方案。但是,我对此并不满意,因为我正在测试订阅方法的内部实现。
      • Microsoft Shims 和 Stubs 仅适用于 VS 2012 Ultimate 和 Premium 及以上版本......我仍然坚持使用 VS 2010 Professional.. 是时候和我的老板谈谈了 ;)
      • 是的,这是真的。您需要为此进行升级。
      • 您知道是否每个人都需要获得 Ultimate 或 Premium 许可证? 2013 Pro 和 Premium 之间的价格差异是 8.... 我想我可以让我的老板给我一个 Premium.... 但不是 10....
      猜你喜欢
      • 2020-04-24
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-24
      • 2022-06-27
      相关资源
      最近更新 更多