cho*_*bo2 19 c# asp.net-mvc unit-testing mocking
所以我的代码中有一些SMTP内容,我正在尝试对该方法进行单元测试.
所以我一直在尝试使用Mockup MailMessage但它似乎永远不会起作用.我认为没有一种方法是虚拟的或抽象的,所以我不能用moq来模拟它:(.
所以我想我必须手工完成,这就是我被困住的地方.
*手动我的意思是使用界面和包装器,但让moq仍然模拟界面.
我不知道如何编写我的接口和我的Wrapper(一个将实现具有实际MailMessage代码的接口的类,因此当我的真实代码运行时它实际上完成了它需要做的事情).
所以首先我不确定如何设置我的界面.让我们来看看我必须模拟的其中一个字段.
MailMessage mail = new MailMessage();
mail.To.Add("test@hotmail.com");
Run Code Online (Sandbox Code Playgroud)
所以这是我要假装的第一件事.
所以看着它我知道"To"是一个属性,通过命中F12而不是"To"它需要我这一行:
public MailAddressCollection To { get; }
Run Code Online (Sandbox Code Playgroud)
所以它是MailAddressCollection属性.但有些我怎么被允许进一步做"添加".
所以现在我的问题是在我的界面中我做了什么?
我要做房产吗?该属性应该是MailAddressCollection吗?
或者我应该有一个像这样的方法?
void MailAddressCollection To(string email);
or
void string To.Add(string email);
Run Code Online (Sandbox Code Playgroud)
那我的包装怎么样?
所以你可以看到我很困惑.因为有这么多.我猜我只是模拟我正在使用的那些.
编辑代码
我想在真正意义上我只需要测试更多异常,但我想测试以确保一切都被发送然后它将得到响应=成功.
string response = null;
try
{
MembershipUser userName = Membership.GetUser(user);
string newPassword = userName.ResetPassword(securityAnswer);
MailMessage mail = new MailMessage();
mail.To.Add(userName.Email);
mail.From = new MailAddress(ConfigurationManager.AppSettings["FROMEMAIL"]);
mail.Subject = "Password Reset";
string body = userName + " Your Password has been reset. Your new temporary password is: " + newPassword;
mail.Body = body;
mail.IsBodyHtml = false;
SmtpClient smtp = new SmtpClient();
smtp.Host = ConfigurationManager.AppSettings["SMTP"];
smtp.Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["FROMEMAIL"], ConfigurationManager.AppSettings["FROMPWD"]);
smtp.EnableSsl = true;
smtp.Port = Convert.ToInt32(ConfigurationManager.AppSettings["FROMPORT"]);
smtp.Send(mail);
response = "Success";
}
catch (ArgumentNullException ex)
{
response = ex.Message;
}
catch (ArgumentException ex)
{
response = ex.Message;
}
catch (ConfigurationErrorsException ex)
{
response = ex.Message;
}
catch (ObjectDisposedException ex)
{
response = ex.Message;
}
catch (InvalidOperationException ex)
{
response = ex.Message;
}
catch (SmtpFailedRecipientException ex)
{
response = ex.Message;
}
catch (SmtpException ex)
{
response = ex.Message;
}
return response;
}
Run Code Online (Sandbox Code Playgroud)
谢谢
Jer*_*rey 32
为什么要模拟MailMessage?SmtpClient接收MailMessages并将它们发送出去; 这是我想要用于测试目的的类.因此,如果您正在编写某种类型的放置订单的系统,如果您尝试测试订单放置后您的OrderService始终发送电子邮件,那么您将拥有类似于以下内容的类:
class OrderService : IOrderSerivce
{
private IEmailService _mailer;
public OrderService(IEmailService mailSvc)
{
this. _mailer = mailSvc;
}
public void SubmitOrder(Order order)
{
// other order-related code here
System.Net.Mail.MailMessage confirmationEmail = ... // create the confirmation email
_mailer.SendEmail(confirmationEmail);
}
}
Run Code Online (Sandbox Code Playgroud)
使用IEtService的默认实现包装SmtpClient:
这样,当您编写单元测试时,您将测试使用SmtpClient/EmailMessage类的代码的行为,而不是SmtpClient/EmailMessage类本身的行为:
public Class When_an_order_is_placed
{
[Setup]
public void TestSetup() {
Order o = CreateTestOrder();
mockedEmailService = CreateTestEmailService(); // this is what you want to mock
IOrderService orderService = CreateTestOrderService(mockedEmailService);
orderService.SubmitOrder(o);
}
[Test]
public void A_confirmation_email_should_be_sent() {
Assert.IsTrue(mockedEmailService.SentMailMessage != null);
}
[Test]
public void The_email_should_go_to_the_customer() {
Assert.IsTrue(mockedEmailService.SentMailMessage.To.Contains("test@hotmail.com"));
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:为了解决您的评论,您需要两个单独的EmailService实现 - 只有一个将使用SmtpClient,您将在应用程序代码中使用它:
class EmailService : IEmailService {
private SmtpClient client;
public EmailService() {
client = new SmtpClient();
object settings = ConfigurationManager.AppSettings["SMTP"];
// assign settings to SmtpClient, and set any other behavior you
// from SmtpClient in your application, such as ssl, host, credentials,
// delivery method, etc
}
public void SendEmail(MailMessage message) {
client.Send(message);
}
}
Run Code Online (Sandbox Code Playgroud)
你的模拟/伪造电子邮件服务(你不需要一个模拟框架,但它有帮助)不会触及SmtpClient或SmtpSettings; 它只记录了一个事实,即在某个时候,一封电子邮件通过SendEmail传递给它.然后,您可以使用它来测试是否调用了SendEmail,以及使用哪些参数:
class MockEmailService : IEmailService {
private EmailMessage sentMessage;;
public SentMailMessage { get { return sentMessage; } }
public void SendEmail(MailMessage message) {
sentMessage = message;
}
}
Run Code Online (Sandbox Code Playgroud)
电子邮件是否已发送到SMTP服务器并交付的实际测试应超出单元测试的范围.您需要知道这是否有效,并且您可以设置第二组测试来专门测试它(通常称为集成测试),但这些是与测试应用程序核心行为的代码分开的不同测试.
归档时间: |
|
查看次数: |
8568 次 |
最近记录: |