Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using FakeItEasy to assert that an event was raised

I can do the following to verify if the ErrorOccurred event of my Consumer class was raised:

using System;
using FakeItEasy;
using Microsoft.VisualStudio.TestTools.UnitTesting;

public interface IService
{
    event EventHandler SomethingBadHappened;
}

class Consumer
{
    private readonly IService service;

    public Consumer(IService service)
    {
        this.service = service;
        service.SomethingBadHappened += (sender, args) => RaiseErrorOccurred();
    }

    public event EventHandler ErrorOccurred;

    protected virtual void RaiseErrorOccurred()
    {
        var handler = ErrorOccurred;
        if (handler != null) handler(this, EventArgs.Empty);
    }
}

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var service = A.Fake<IService>();
        var consumer = new Consumer(service);

        bool eventWasRaised = false;
        consumer.ErrorOccurred += (sender, args) => { eventWasRaised = true; };

        service.SomethingBadHappened += Raise.WithEmpty();

        Assert.IsTrue(eventWasRaised);
    }
}

I wonder if there is a more "Mocking Framework-y" way of doing this. Something like the below would be nice:

        var service = A.Fake<IService>();
        var consumer = new Consumer(service);

        service.SomethingBadHappened += Raise.WithEmpty();

        consumer.ErrorOccurred.MustHaveHappened(/*yada yada/*);
like image 548
johnildergleidisson Avatar asked Sep 18 '25 09:09

johnildergleidisson


1 Answers

For FakeItEasy to perform any assertions on methods, the method must be fakeable, and defined on a fake object. In this case, consumer is a "real" object, so there's no way for FakeItEasy to know whether it did anything.

There's an alternative, but whether it's more "Mocking Framework-y" or not is up for debate. But it may appeal to you.

Create a fake (in this case handler) to listen to the ErrorOccurred method:

[TestMethod]
public void TestMethod2()
{
    var service = A.Fake<IService>();
    var consumer = new Consumer(service);

    var handler = A.Fake<EventHandler>();
    consumer.ErrorOccurred += handler;

    service.SomethingBadHappened += Raise.WithEmpty();

    A.CallTo(()=>handler.Invoke(A<object>._, A<EventArgs>._)).MustHaveHappened();
}

That way you can check to see if the handler was called. There are straightforward modifications that could be made to ensure that the call was made a specific number of times, or with certain arguments.

Of course, if you don't care about the number of times the method was called, or the arguments, since there's really only one method of interest on handler, you could potentially use this simpler call, which will match any call to the handler (probably Invoke):

A.CallTo(handler).MustHaveHappened();
like image 69
Blair Conrad Avatar answered Sep 21 '25 00:09

Blair Conrad