从理论上讲简单的问题。如果我有Email
类,其中有Send()
个方法,该类负责发送电子邮件。 Send()
方法在名为IEmail
的接口中声明。假设我将在单元测试中以moq
接口的方式IEmail
。然后,当我与Setup
一起使用Send()
起订量,并随后使用Verify()
方法时,我想将不会发送真实的电子邮件,而仅检查Send()
方法是否被正确调用。我对吗?其次要检查真实的Send()
才能真正发送电子邮件,我应该使用集成测试。都对吗?
答案 0 :(得分:2)
大概您要测试的不是实际的Email
类。如果是发送电子邮件的具体类,则调用Send
将(并且可能应该)发送电子邮件。
模拟对于测试{em> 依赖于IEmail
接口的类很有用。它使您可以验证您的类对它所依赖的接口执行了预期的操作。在这种情况下,您将不想发送电子邮件。您只想测试您的班级告诉IEmail
发送电子邮件。
这是一个人为设计的类示例,该类依赖于IEmail
接口来发送电子邮件。
public class ClassThatSendsEmail
{
private readonly IEmail _email;
public ClassThatSendsEmail(IEmail email)
{
_email = email;
}
public void DoSomethingThatCausesAnEmailToGetSent()
{
var message = new Message {To = "bob@bob.com", Body = "Hi, Bob!"};
_email.Send(message);
}
}
...这是我为了测试而拼凑的其他一些类型:
public interface IEmail
{
void Send(Message message);
}
public class Message
{
public string To { get; set; }
public string Body { get; set; }
}
这是一个非常简单的测试,可以模拟IEmail
。
public class Tests
{
[TestCase]
public void MyClassSendsAnEmail()
{
var emailMock = new Mock<IEmail>();
emailMock.Setup(x=>x.Send(It.IsAny<Message>())).Verifiable();
var subject = new ClassThatSendsEmail(emailMock.Object);
subject.DoSomethingThatCausesAnEmailToGetSent();
emailMock.Verify(x=>x.Send(It.IsAny<Message>()));
}
}
要直接回答您的问题,将不会发送电子邮件,因为具体的Email
类在图片中不存在。我什至还没有创造一个。我的课程仅取决于接口,因此我可以在编写IEmail
的实现之前对其进行测试。该测试只是要验证我的类是否调用了该模拟程序的Send
方法。
(这是防止耦合的一种好方法。我不希望我的班级与发送电子邮件的其他班级紧密耦合,以便一个班级只能与另一个班级一起工作。如果第一班按预期工作当我甚至还没有创建第二类时,它就没有与第二类耦合。)
有时候,编写一个double测试很方便,这是一个实际的类,仅出于测试目的而实现了接口。您可以使用Moq进行相同的操作,但有时所有设置代码都会变得很复杂,并且使用测试倍数只会使其更易于阅读。
因此,这是IEmail
的测试倍数。当您发送消息时,它将把消息添加到列表中。这样,在测试运行之后,您可以查看列表中的内容以查看是否发送了正确的电子邮件:
public class EmailListDouble : List<Message>, IEmail
{
public void Send(Message message)
{
Add(message);
}
}
现在,您可以轻松编写一个测试来验证是否调用了IEmail.Send
并且已发送了预期的消息:
[TestCase]
public void MyClassSendsAnEmail()
{
var email = new EmailListDouble();
var subject = new ClassThatSendsEmail(email);
subject.DoSomethingThatCausesAnEmailToGetSent();
Assert.True(email.Any(message=> message.To == "bob@bob.com" && message.Body.Contains("Bob")));
}
Moq很不错,但是有时设置不仅变得有点麻烦,而且还使得很难说出正在测试的内容。有时只需使用两次测试即可完成工作,而且更容易。