使用Moq调用方法时如何引发事件?

我有这样的界面:

public interface IMyInterface { event EventHandler Triggered; void Trigger(); } 

我的unit testing中有一个模拟对象,如下所示:

 private Mock _mockedObject = new Mock(); 

我想做这样的事情:

 // pseudo-code _mockedObject.Setup(i => i.Trigger()).Raise(i => i.Triggered += null, this, true); 

但是,在返回的ISetup接口上看起来不像Raise 。 我该怎么做呢?

你的伪代码几乎就是现实。 你需要使用Raises而不是Raise 。 检查Moq快速入门: Moq 4.x版本的事件 ,您将看到出错的地方。

 _mockedObject.Setup(i => i.Trigger()).Raises(i => i.Triggered += null, this, true); 

这是GitHub的代码片段

 // Raising an event on the mock mock.Raise(m => m.FooEvent += null, new FooEventArgs(fooValue)); // Raising an event on a descendant down the hierarchy mock.Raise(m => m.Child.First.FooEvent += null, new FooEventArgs(fooValue)); // Causing an event to raise automatically when Submit is invoked mock.Setup(foo => foo.Submit()).Raises(f => f.Sent += null, EventArgs.Empty); // The raised event would trigger behavior on the object under test, which // you would make assertions about later (how its state changed as a consequence, typically) // Raising a custom event which does not adhere to the EventHandler pattern public delegate void MyEventHandler(int i, bool b); public interface IFoo { event MyEventHandler MyEvent; } var mock = new Mock(); ... // Raise passing the custom arguments expected by the event delegate mock.Raise(foo => foo.MyEvent += null, 25, true); 

所以我弄清楚我做错了什么。 我将在这里发布答案但是给予Nkosi的功劳,因为我没有真正正确地提出这个问题,他提供了很多有用的信息。

使用模拟上的异步方法,您需要首先指定它返回任务,然后才能触发事件。 所以在我的例子中(意识到我应该有Task Trigger();作为方法签名,这是我正在寻找的代码:

 _mockedObject.Setup(i => i.Trigger()) .Returns(Task.FromResult(default(object))) .Raise(i => i.Triggered += null, this, true); 

显然,这可以在C#4.6中进一步简化,对此:

 _mockedObject.Setup(i => i.Trigger()) .Returns(Task.CompletedTask) .Raise(i => i.Triggered += null, this, true); 

扩展SoaperGEM的答案,所有返回内容的方法(无论类型)必须在触发事件之前指定返回值。 由于异步方法返回Task ,异步方法属于此类别。 我有一个返回string的方法,我试图弄清楚为什么我不能用Mock对象触发事件。 然后我尝试先返回,它工作得很好。

以SoaperGEM为例,假设Trigger()返回一个字符串:

 _mockedObject.Setup(i => i.Trigger()) .Returns("somestring") .Raises(i => i.Triggered += null, this, true);