为什么我的Moq IEventAggregator验证失败?

时间:2021-01-24 15:38:50

I use Composite WPF(Prism) and I am trying to unit test that my Controller does in fact subscribe to a Composite Event.

我使用复合WPF(Prism),我正在尝试单元测试我的Controller实际上订阅了一个复合事件。

My subscription code looks as follows...

我的订阅代码如下......

//Init Events.
this.eventAggregator.GetEvent<PlantTreeNodeSelectedEvent>().Subscribe(
    ShowNodeDetails, ThreadOption.UIThread);

My unit testing code looks as follows (I use Moq as my Mocking Framework and Unity as my DI Framework)...

我的单元测试代码如下(我使用Moq作为我的Mocking Framework,Unity作为我的DI框架)...

Mock<PlantTreeNodeSelectedEvent> eventBeingListenedTo = new Mock<PlantTreeNodeSelectedEvent>();
eventAggregatorMock.Setup(e => e.GetEvent<PlantTreeNodeSelectedEvent>()).Returns(eventBeingListenedTo.Object);


//Initialize the controller to be tested.
IPlantTreeController controllerToTest = container.Resolve<IPlantTreeController>();


//Verify.
eventBeingListenedTo.Verify(
    e => e.Subscribe(It.IsAny<Action<string>>(), ThreadOption.UIThread));

This subscribe method IS being called (I've verified by running with the debugger), but the Verify always fails with "Invocation was not performed on the mock: e => e.Subscribe..."

这个订阅方法被调用(我已经通过运行调试器进行了验证),但是验证总是失败并且“在模拟上没有执行调用:e => e.Subscribe ...”

Any idea what I am doing wrong?

知道我做错了什么吗?

3 个解决方案

#1


In your code, it seems like the eventAggregatorMock instance is never used. I would guess that you need to register it with the container so that it is being used by controllerToTest.

在您的代码中,似乎从未使用eventAggregatorMock实例。我猜你需要在容器中注册它,以便controllerToTest使用它。

#2


  1. You seem to be testing too much in your unit test. You shouldn't need a container, you should just create your controller providing mock dependencies, because you should only test 1 thing in a unit test (you don't need to test that the DI framework works, as it usually does ;-)). It will also ensure that you provide the correct mocks, now it is not clear from your code as Mark Seemann has pointed out in his answer.

    您似乎在单元测试中测试过多。你不应该需要一个容器,你应该只创建你的控制器提供模拟依赖,因为你应该只在单元测试中测试1件事(你不需要测试DI框架的工作原理,因为它通常会这样做;-) )。它还将确保您提供正确的模拟,现在您的代码中不清楚Mark Seemann在他的回答中指出的。

  2. You may try to setup a method call under question in the beginning. Sometimes it seems to help moq to verify the class appropriately. In this case you may also want to setup your mock behavior to be Strict in the constructor, so that you will get the test failed for other, unexpected calls to your mock.

    您可以尝试在开头设置问题中的方法调用。有时它似乎有助于moq适当地验证课程。在这种情况下,您可能还希望在构造函数中将模拟行为设置为Strict,这样您将无法对模拟的其他意外调用进行测试。


eventBeingListenedTo.Setup(e => e.Subscribe(It.IsAny<Action<string>>(), ThreadOption.UIThread));

#3


use a mocking aggregator like this (for Rhino.Mocks) http://adammills.wordpress.com/2010/12/13/auto-mocking-eventaggregator/

使用像这样的模拟聚合器(对于Rhino.Mocks)http://adammills.wordpress.com/2010/12/13/auto-mocking-eventaggregator/

If you use ThreadOption.UIThread, it calls Dispatcher.Invoke which won't work without a Message Loop; which isn't normally running in unit tests.

如果你使用ThreadOption.UIThread,它会调用Dispatcher.Invoke,如果没有Message Loop,它将无法工作;通常不会在单元测试中运行。

#1


In your code, it seems like the eventAggregatorMock instance is never used. I would guess that you need to register it with the container so that it is being used by controllerToTest.

在您的代码中,似乎从未使用eventAggregatorMock实例。我猜你需要在容器中注册它,以便controllerToTest使用它。

#2


  1. You seem to be testing too much in your unit test. You shouldn't need a container, you should just create your controller providing mock dependencies, because you should only test 1 thing in a unit test (you don't need to test that the DI framework works, as it usually does ;-)). It will also ensure that you provide the correct mocks, now it is not clear from your code as Mark Seemann has pointed out in his answer.

    您似乎在单元测试中测试过多。你不应该需要一个容器,你应该只创建你的控制器提供模拟依赖,因为你应该只在单元测试中测试1件事(你不需要测试DI框架的工作原理,因为它通常会这样做;-) )。它还将确保您提供正确的模拟,现在您的代码中不清楚Mark Seemann在他的回答中指出的。

  2. You may try to setup a method call under question in the beginning. Sometimes it seems to help moq to verify the class appropriately. In this case you may also want to setup your mock behavior to be Strict in the constructor, so that you will get the test failed for other, unexpected calls to your mock.

    您可以尝试在开头设置问题中的方法调用。有时它似乎有助于moq适当地验证课程。在这种情况下,您可能还希望在构造函数中将模拟行为设置为Strict,这样您将无法对模拟的其他意外调用进行测试。


eventBeingListenedTo.Setup(e => e.Subscribe(It.IsAny<Action<string>>(), ThreadOption.UIThread));

#3


use a mocking aggregator like this (for Rhino.Mocks) http://adammills.wordpress.com/2010/12/13/auto-mocking-eventaggregator/

使用像这样的模拟聚合器(对于Rhino.Mocks)http://adammills.wordpress.com/2010/12/13/auto-mocking-eventaggregator/

If you use ThreadOption.UIThread, it calls Dispatcher.Invoke which won't work without a Message Loop; which isn't normally running in unit tests.

如果你使用ThreadOption.UIThread,它会调用Dispatcher.Invoke,如果没有Message Loop,它将无法工作;通常不会在单元测试中运行。