Home > Enterprise >  Moq Verify doesn't seem to be working for generic methods
Moq Verify doesn't seem to be working for generic methods

Time:01-02

I'm trying to verify that a method with a generic argument gets called but I can't get the test to pass even though it runs without mocking.

I've got a test method:

var mockBus = new Mock<MessageBus>();
mockBus.Setup(e => e.PublishEvent(It.IsAny<EventToVerify>())).Verifiable();
var repo = new Repository(mockBus.Object);

Entity ent = new Entity();
ent.ApplyEvent(new EventToVerify("New Data"));
repo.Save(ent);
mockBus.Verify(e=>e.PublishEvent(It.IsAny<EventToVerify>()), Times.AtLeastOnce);

The verify is always failing with no invocations. I know it does get called though since a breakpoint on it gets hit when I don't mock it. Am I not setting up the Mock correctly?

Here's the rest of the code for context:

public class Event
{
    public readonly Guid CorrelationId;

    public Event()
    {
        CorrelationId = Guid.NewGuid();
    }
}

public class EventToVerify : Event
{
    public readonly string Data;
    public EventToVerify(string data)
    {
        Data = data;
    }
}

public interface IEventPublisher
{
    public void PublishEvent<T>(T ev) where T: Event;
}

public class MessageBus : IEventPublisher
{
    public virtual void PublishEvent<T>(T ev) where T : Event 
    {
        Console.WriteLine("------------------Event WAS published: "   ev.CorrelationId);
    }
}

public class Entity
{
    private IList<Event> _events;

    public string Data { get; private set; }

    public Entity()
    {
        Data = "Nothing";
        _events = new List<Event>();
    }

    public void ApplyEvent(EventToVerify ev)
    {
        Data = ev.Data;

        _events.Add(ev);
    }

    public IList<Event> GetEvents()
    {
        return _events;
    }
}

public class Repository
{
    private IEventPublisher _publisher;
    public Repository(IEventPublisher publisher)
    {
        _publisher = publisher;
    }

    public void Save(Entity e)
    {
        //persistence logic here

        foreach (var ev in e.GetEvents())
        {
            _publisher.PublishEvent(ev);
        }
    }
}

I have a repro project here: https://github.com/amguilmet/MoqNotMoqinExample

CodePudding user response:

It is a casting issue. IList<Event> GetEvents() at

//...Repository
public void Save(Entity e) {
    //persistence logic here
    foreach (var ev in e.GetEvents()) {
        _publisher.PublishEvent(ev);
    }
}

means that when the test is exercised the mock is actually recoding Event being passed into the mocked member.

I tested the code by changing to

//...

mockBus.Verify(e => e.PublishEvent(It.IsAny<Event>()), Times.AtLeastOnce);

//...

and it passes with no issue.

Even the following works with no issue as well

//...

mockBus.Verify(e => e.PublishEvent<Event>(It.IsAny<EventToVerify>()), Times.AtLeastOnce);

//...

The mock's expectations needed to be explicitly defined to behave as expected since the implied generic argument in the original example had unwanted results.

  • Related