It seems that when an exception is raised inside an event raise, it gets caught by Moq and it goes undetected. Might have to do with it being async? (Getting caught inside Task.Exception).
Example:
internal class Program
{
static async Task Main(string[] args)
{
var eventManager = new EventManager();
var eventConsumer = new EventConsumer(eventManager);
await eventManager.OnEventHappened(1000);
Console.WriteLine("Unreacheble, exception thrown");
}
}
public delegate Task CustomEvent(int number);
public interface IEventManager
{
event CustomEvent CustomEvent;
}
public class EventConsumer
{
private readonly IEventManager _eventManager;
public EventConsumer(IEventManager eventManager)
{
_eventManager = eventManager;
_eventManager.CustomEvent += _eventManager_CustomEvent;
}
private async Task _eventManager_CustomEvent(int number)
{
await Task.Delay(number);
throw new NotImplementedException();
}
}
public class EventManager : IEventManager
{
public event CustomEvent CustomEvent;
public async Task OnEventHappened(int number)
{
await CustomEvent.Invoke(number);
}
}
For instance, these tests are failing (expected exception but was null).
[Test]
public void ShouldThrowException()
{
var eventManagerMock = new Mock<IEventManager>(MockBehavior.Strict);
var consumer = new EventConsumer(eventManagerMock.Object);
Assert.Throws<NotImplementedException>(() => eventManagerMock.Raise(x => x.CustomEvent += null, 1000));
}
[Test]
public void ShouldThrowException2()
{
var eventManagerMock = new Mock<IEventManager>(MockBehavior.Strict);
var consumer = new EventConsumer(eventManagerMock.Object);
eventManagerMock.Setup(x => x.OnEventHappened(1000)).Returns(Task.CompletedTask).Raises(x => x.CustomEvent += null, 1000);
Assert.ThrowsAsync<NotImplementedException>(() => eventManagerMock.Object.OnEventHappened(1000));
}
Am I doing something wrong or is it a bug indeed?
I have opened an issue on moq's repro, but got no response there so far.
Thanks!