Модульное тестирование / Как утверждать, что немодальный метод назывался / C # / Rhino Mocks / NUnit - PullRequest
0 голосов
/ 26 августа 2010

У меня есть MailService, который позволяет мне отправлять электронную почту, которая реализует следующий интерфейс.

public interface IMailService
  {
    bool SendRegisteringEmail(RegisterModel registerModel);
    bool SendMail(MailMessage mailMessage);
    MailMessage CreateRegisteringMailMessage(RegisterModel registerModel);

    IAppSettingsRepository AppSettingsRepository { get; set; }

    ISmtpClient SmtpClient { get; set; }
  }

Функция SendRegisteringEmail должна вызвать CreateRegisteringMailMessage, затем передать возвращаемое MailMessage в функцию SendMail, а SendRegisteringEmail должна вернуть возвращаемое логическое значение SendMail.

Я использую тесты NUnit и Rhino Mocks, я новичок в тестировании (1 неделя) и практикую TDD (по крайней мере, я стараюсь). Моя проблема в том, что я не знаю, как утверждать, что CreateRegisteringMailMessage был вызван, когда я вызываю SendRegisteringEmail, потому что MailService не является Mocked Object. Вот мой тест:

[Test]
public void SendRegisteringEmail_ShouldCallCreateRegisteringMailMessage()
{
  //Arrange
  //MailMessage mailMessage = new MailMessage();
  IMailService mailService = new MailService { AppSettingsRepository = CreateAppSettingsMockReposotory() };
  //ISmtpClient smtpClientStub = MockRepository.GenerateStub<ISmtpClient>();
  //mailService.SmtpClient = smtpClientStub;
  //smtpClientStub.Stub(f => f.Send(mailMessage)).Return(true);


  //Act
  mailService.SendRegisteringEmail(ValidRegisterModel);

  //Assert
  mailService.AssertWasCalled(f => f.CreateRegisteringMailMessage(ValidRegisterModel));
}

При запуске теста я получаю следующую ошибку: FtpWeb.Tests.MailServiceTests.SendRegisteringEmail_ShouldCallCreateRegisteringMailMessage: System.InvalidOperationException: объект FtpWeb.Models.MailService не является поддельным объектом.

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

Спасибо.

Ответы [ 3 ]

3 голосов
/ 26 августа 2010

Я не уверен, что вы должны проверить, что CreateRegisteringMailMessage вызывается. Вы должны просто проверить исход звонка SendRegisteringEmail. Что это должно делать с вашей реализацией MailService? Предположительно, это повлияет на другой сервис - так что проверьте это.

Это был бы странный дизайн интерфейса, который настаивал на том, что вызов одного метода потребует вызова другого метода в интерфейсе - довольно часто вы можете заставить оба метода вызывать один частный, общий метод, например.

1 голос
/ 26 августа 2010

Методы CreateRegisteringMailMessage и SendMail представляются на более низком уровне абстракции, чем SendRegisteringEmail.Вы могли бы рассмотреть возможность создания класса более высокого уровня, содержащего SendRegisteringEmail, и этот класс использовал бы IMailService, который вы могли бы высмеивать и утверждать, как обычно.

Если первое решение не является вариантом, то вы должны обработать SendRegisteringEmail В целом, настолько эффективно, что вы должны тестировать побочные эффекты CreateRegisteringMailMessage и SendMail в одном тесте (немного запах кода, отсюда мое предложение извлечь еще один уровень косвенности) - см. ответ Джона.

0 голосов
/ 26 августа 2010

Это часто называют «восприятием» в тестируемом классе: вы должны найти способ узнать, был ли вызван метод. Подобные вещи хорошо освещены в книге « Эффективная работа с устаревшим кодом », которую должен иметь каждый (отказ от ответственности: я не имею отношения к автору книги, я просто думаю, что это хорошая книга)

Что делает метод CreateRegisteringMailMessage? Влияет ли это на содержимое экземпляра RegisterModel, переданного во время вызова?

...