Как проверить, что метод был вызван?

У меня есть класс ICreateService, который зависит от ITicketApiAdapter. Я попытался зарегистрировать фиктивный ITicketAdaper, чтобы он вводился, когда я создаю анонимную службу создания.

Итак, в настройке у меня есть этот регистр для адаптера билетов:

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));

Насколько я понимаю, это должно «заморозить» как ICreateService, так и Mock<ITicketApiAdapter>, так что когда я запрашиваю анонимный экземпляр, это тот, который я зарегистрировал.

У меня есть тест, который выглядит так:

[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));

}

Я ожидаю, что apiTicketAdapter будет тем, что я зарегистрировал, чтобы я мог проверить, что метод вызван. Если я перейду, вызывается TicketApiAdapter, но Moq говорит, что это не так.

Редактировать

Это ошибка, которую я получаю:

CreateServiceCallsAddTicketComment сгенерировал исключение: Moq.MockException: ожидался вызов в макете один раз, но был 0 раз: x => x.AddTicketComment (It.IsAny (), It.IsAny (), It.IsAny ())

Настроенные настройки: x => x.AddTicketComment (It.IsAny (), It.IsAny (), It.IsAny ()), Times.Never Вызовы не выполнялись.


person scottm    schedule 09.11.2011    source источник
comment
Какое именно сообщение Moq показано?   -  person Serghei    schedule 09.11.2011
comment
@Serghei добавил сообщение об ошибке   -  person scottm    schedule 09.11.2011
comment
Добавьте код метода AddTicketComment (), пожалуйста   -  person Serghei    schedule 09.11.2011
comment
Это в первом блоке кода. Это просто макет, который дает хороший результат.   -  person scottm    schedule 09.11.2011
comment
Я не понимаю, почему вы ожидаете, что метод AddTicketComment () вызывается в x.AddTicketComment (), если вы вообще не вызываете его в этом методе, у вас нет реализации CreateSerice, как я правильно понял. Как я понял в классе CreateService у вас должен быть метод x.AddTicketComment (), и этот метод должен вызывать AddTicketComment ()? можешь показать реализацию CreateService?   -  person Serghei    schedule 09.11.2011
comment
CreateService вызывает ITicketApiAdapter.AddTicketComment() внутри CreateService.AddTicketComment(). Итак, когда я звоню CreateService.AddTicketComment(), я ожидаю, что он позвонит ITicketApiAdapter.AddTicketComment()   -  person scottm    schedule 09.11.2011
comment
Вы уверены, что этот Fixture.CreateAnonymous ‹Mock ‹ITicketApiAdapter›› (). вернуть тот же экземпляр, что и в настройке и методе тестирования?   -  person Serghei    schedule 09.11.2011
comment
Нет. Вот почему я разместил это. Насколько я понимаю AutoFixture, когда вы регистрируете экземпляр, он возвращается каждый раз, когда вы запрашиваете анонимную версию этого типа, но, похоже, он этого не делает.   -  person scottm    schedule 09.11.2011
comment
+1 за то, что познакомил меня с AutoFixture. Похоже, это очень хороший инструмент, и автоматизация поддерживается более активно, чем аналоги DI (я использую Autofac) (это много авто- *).   -  person Marc L.    schedule 10.11.2011


Ответы (1)


Когда вы регистрируете блок кода, этот блок кода будет вызываться каждый раз, когда экземпляр Fixture разрешает запрошенный тип. Это означает, что он не заморожен. Если вы хотите что-то заморозить, часто проще выполнить одну из перегрузок по замораживанию. использовать.

Еще лучше, поскольку вы, похоже, используете Moq, могу ли я предложить использовать расширение AutoMoq < / а>?

Это позволит вам переписать тест примерно так:

[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));

}

Предполагается, что CreateTicketRequest использует внедрение конструктора или свойство.

person Mark Seemann    schedule 09.11.2011
comment
Спасибо, Марк. Я читал ваш блог, но, похоже, не могу полностью разобраться в функциях AutoFixture / AutoMoq. Простой тест кажется достаточно легким, но мне не хватает полной настройки. Я хочу иметь возможность настроить apiTicketAdapter один раз, а затем протестировать все методы в CreateService, вызывающие разные методы адаптера. Если я бесплатно использую адаптер билетов в [TestSetup], могу ли я использовать Freeze в каждом [TestMehtod], чтобы получить тот же экземпляр для проверки вызова метода? - person scottm; 10.11.2011
comment
Ответил на мой собственный вопрос, просто попробовав;) похоже, он делает то, что я ожидал. Кстати, когда я пытаюсь зайти в ваш блог из результатов поиска Google, Chrome каждый раз вылетает. - person scottm; 10.11.2011
comment
Строка 6 вашего примера кода должна быть apiTicketAdaptor, а не ticketApiAdaptor? - person OutstandingBill; 10.03.2021
comment
@OutstandingBill Наверное, стоит ... - person Mark Seemann; 10.03.2021