How do I assert a method was called on this mocked dependency with moq and mspec?

StackOverflow https://stackoverflow.com/questions/8083249

  •  26-02-2021
  •  | 
  •  

I was testing a model repository to see if it calls the message bus. I am not sure if this is a good test at all but here is my thinking: I would normally put the bus.send into the controller (this is an MVC web app) but since I don't want to test my controllers specifically for logic, I moved this into the repository. Controllers are simple in my case. Repository uses the bus and the model database to build the view models.

Anyways, point of this problem is the moq test I am running. I mocked the bus and wanted to verify that it is called from the repository.

The test looks like this:

public class when_creating_new_clinic
{
    Establish context = () =>
    {
        clinicID = Guid.NewGuid();
        model = new ClinicModel
        {
            ClinicID = clinicID,
            Alias = "alias",
            Title = "title"
            // stuff omitted
        };
        newClinicData = new NewClinicData
        {
            ClinicID = clinicID,
            Alias = "alias",
            Title = "title"
            // stuff omitted 
        };
        cmd = new CreateClinicCmd(newClinicData);
        bus = new Mock<IMessageBusAgent>();
        repository = new ClinicModelRepository(bus.Object);

        bus.Setup(b => b.Send(cmd));
    };

    Because it = () => repository.Create(model);

    It should_send_create_clinic_command_to_bus = () =>
    {
        bus.Verify(b => b.Send(cmd), Times.Exactly(1));
    };

    static ClinicModelRepository repository;
    static ClinicModel model;
    static Mock<IMessageBusAgent> bus;
    static NewClinicData newClinicData;
    static Guid clinicID;
    static CreateClinicCmd cmd;
}

The gist of the repository is this:

public class ClinicModelRepository : IClinicModelRepository
{
    private readonly IMessageBusAgent m_bus;

    public ClinicModelRepository(IMessageBusAgent bus)
        : this()
    {
        m_bus = bus;
    }

    public void Create(ClinicModel clinicModel)
    {
        // stuff omitted (data is mapped from clinicModel)          

        m_bus.Send(new CreateClinicCmd(data));
    }
}

The IMessageBusAgent is declared as:

public interface IMessageBusAgent : IDomainCommandSender, IDomainEventPublisher, IUnitOfWork
{
}

The result of the test looks like this:

when creating new clinic

» should send create clinic command to bus (FAIL)

Test 'should send create clinic command to bus' failed: Moq.MockException: Expected invocation on the mock exactly 1 times, but was 0 times: b => b.Send(when_creating_new_clinic.cmd)

Configured setups:
b => b.Send<CreateClinicCmd>(when_creating_new_clinic.cmd), Times.Never

Performed invocations:
IDomainCommandSender.Send(ArReg.Commands.CreateClinicCmd)
IUnitOfWork.Commit()
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable`1 setups, IEnumerable`1 actualCalls, Expression expression, Times times, Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
at Moq.Mock.Verify[T](Mock mock, Expression`1 expression, Times times, String failMessage)
at Moq.Mock`1.Verify(Expression`1 expression, Times times)
Repositories\when_creating_new_clinic.cs(51,0): at ArReg.Tests.Specs.Repositories.when_creating_new_clinic.<.ctor>b__4()
at Machine.Specifications.Model.Specification.InvokeSpecificationField()
at Machine.Specifications.Model.Specification.Verify()

0 passed, 1 failed, 0 skipped, took 3.58 seconds (Machine.Specifications 0.4.24-f7fb6b5).

The Send() command is declared in the IDomainCommandSender so how do I need to setup the test so that I can verify the correct call?

Thanks

有帮助吗?

解决方案

Your setup of the bus-moq has a little mistake. It should be like this:

bus.Setup(b => b.Send(It.IsAny<CreateClinicCmd>()));

Reason: You wrote your setup with an instance of CreateClinicCmd created two code lines above. In your class under test ClinicModelRepository you create another instance of that class and call your bus mock. This call doesn't match the call you wrote in your setup.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top