我有一个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,然后将SendMessage返回给SendMail函数,SendRegisteringEmail应该返回SendMail的返回布尔值。
我正在使用NUnit和Rhino Mocks进行测试,我是新手测试(1周),我正在练习TDD(至少我尝试过)。我的问题是我不知道如何在调用SendRegisteringEmail时断言CreateRegisteringMailMessage被调用,因为MailService不是Mocked对象。 这是我的测试:
[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'不是模拟对象。
我理解为什么我会收到此错误但现在如何测试我的通话。 因为它是同一个对象我不能嘲笑它来测试它。 如果有人能帮我解决这个问题。
感谢。
答案 0 :(得分:3)
我不确定应该测试是否CreateRegisteringMailMessage
被调用。您应该只是检查调用SendRegisteringEmail
的结果。您的MailService
实施应该怎么做?据推测它会对另一项服务产生一些影响 - 所以测试一下。
这将是一个奇怪的接口设计,坚持调用一个方法将需要调用接口中的另一个方法 - 通常你可能会让两个方法调用一个私有的,常见的方法,例如。
答案 1 :(得分:1)
方法CreateRegisteringMailMessage
和SendMail
似乎在比SendRegisteringEmail
更低的抽象级别上。你可以考虑创建一个包含SendRegisteringEmail
的更高级别的类,这个类将使用IMailService,你可以照常模拟和断言。
如果第一个解决方案不是一个选项,那么您应该将SendRegisteringEmail
视为一个整体,因此您必须在单个方面测试CreateRegisteringMailMessage
和SendMail
的副作用测试(有点代码味道,因此我建议提取另一层次的间接) - 见Jon的回答。
答案 2 :(得分:0)
这通常被称为被测试类中的“感知”:您必须找到一种方法来判断方法是否已被调用。每个人都应该拥有的“Working Effectively with Legacy Code”一书中详细介绍了这些事情(免责声明:我与该书的作者没有任何关系,我认为这本书很好)。
CreateRegisteringMailMessage
方法有什么作用?它是否会影响呼叫期间传入的RegisterModel
实例的内容?