简体   繁体   中英

How do I raise an event when a method is called using Moq?

I've got an interface like this:

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

And I've got a mocked object in my unit test like this:

private Mock<IMyInterface> _mockedObject = new Mock<IMyInterface>();

I want to do something like this:

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

However it doesn't look like Raise is available on the ISetup interface that gets returned. How do I do this?

Your pseudo-code was almost spot on. You needed to use Raises instead of Raise . Check the Moq Quickstart: Events for versions Moq 4.x and you will see where you made the mistake.

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

Here is the snippet form 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<IFoo>();
...
// Raise passing the custom arguments expected by the event delegate
mock.Raise(foo => foo.MyEvent += null, 25, true);

So I figured out what I was doing wrong. I'm going to post the answer here but give the credit to Nkosi because I didn't really ask the question correctly, and he provided a lot of useful information.

With an async method on a mock, you need to first specify that it returns a Task before you can have it trigger events. So in my example (realizing that I should have had Task Trigger(); as the method signature, this is the code I was looking for:

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

Apparently this can be simplified even further in C# 4.6, to this:

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

Expanding on SoaperGEM's answer, all methods that return something (no matter the type) must have that return value specified before triggering the event. Since async methods return Task , async methods fall into this category. I have a method that returns a string , and I was trying to figure out why I couldn't trigger the event with the Mock object. Then I tried returning first and it worked just fine.

Taking SoaperGEM's example, and assuming Trigger() returns a string:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM