سؤال

I have a ICreateService class that has dependency on ITicketApiAdapter. I've tried registering a mock ITicketAdaper so that it gets injected when I create an anonymous create service.

So, in setup, I have this register for the ticket adapter:

Fixture.Register(() =>
    {
        var ticketApiAdapter = new Mock<ITicketApiAdapter>();
        ticketApiAdapter
            .Setup( x => x.AddTicketComment(
                It.IsAny<User>(), 
                It.IsAny<Customer>(), 
                It.IsAny<TicketComment>()))
        .Returns(new SaveResult
                        {
                            Success = true, 
                            Id = Fixture.CreateAnonymous<Guid>().ToString()
                        });

        return ticketApiAdapter;
    });

Fixture.Register(() => new CreateService(Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>().Object));

From my understanding, that should "freeze" both the ICreateService and Mock<ITicketApiAdapter> so that when I request an anonymous instance, it's the one I registered.

I have a test that looks like this:

[TestMethod]
public void CreateServiceCallsAddTicketComment()
{
    var apiTicketAdapter = Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>();
    var createTicketRequest = Fixture.CreateAnonymous<CreateTicketComment>();
    var createService = Fixture.CreateAnonymous<CreateService>();

    var results = createService.CreateTicketComment(createTicketRequest);

    apiTicketAdapter
        .Verify(x => x.AddTicketComment(
            It.IsAny<User>(), 
            It.IsAny<Customer>(), 
            It.IsAny<TicketComment>()), 
        Times.Once());

    Assert.IsTrue(results.All(x => x.Success));
    Assert.IsTrue(results.All(x => x.Errors.Count == 0));

}

I expect the apiTicketAdapter to be the one I registered so that I can verify the method is called. If I step through, the TicketApiAdapter is called, but Moq says it wasn't.

Edit

This is the error I get:

CreateServiceCallsAddTicketComment threw exception: Moq.MockException: Expected invocation on the mock once, but was 0 times: x => x.AddTicketComment(It.IsAny(), It.IsAny(), It.IsAny())

Configured setups: x => x.AddTicketComment(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never No invocations performed.

هل كانت مفيدة؟

المحلول

When you Register a code block, that code block is going to be invoked every time the Fixture instance resolves the requested type. This means that it's not frozen. If you want to Freeze something, one of the Freeze overloads are often easier to use.

Better yet, since you seem to be using Moq, may I suggest using the AutoMoq extension?

That would enable you to rewrite the test to something like this:

[TestMethod]
public void CreateServiceCallsAddTicketComment(new AutoMoqCustomization());
{
    var fixture = new Fixture().Customize()
    var apiTicketAdapter = fixture.Freeze<Mock<ITicketApiAdapter>>();
    ticketApiAdapter
        .Setup( x => x.AddTicketComment(
            It.IsAny<User>(), 
            It.IsAny<Customer>(), 
            It.IsAny<TicketComment>()))
        .Returns(new SaveResult
        {
            Success = true, 
            Id = Fixture.CreateAnonymous<Guid>().ToString()
        });

    var createTicketRequest = fixture.Freeze<CreateTicketComment>();
    var createService = fixture.CreateAnonymous<CreateService>();

    var results = createService.CreateTicketComment(createTicketRequest);

    apiTicketAdapter
        .Verify(x => x.AddTicketComment(
            It.IsAny<User>(), 
            It.IsAny<Customer>(), 
            It.IsAny<TicketComment>()), 
        Times.Once());

    Assert.IsTrue(results.All(x => x.Success));
    Assert.IsTrue(results.All(x => x.Errors.Count == 0));

}

That's assuming that CreateTicketRequest uses Constructor Injection or Property Injection.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top