单元测试之Stub和Mock-阿里云开发者社区

开发者社区> 开发与运维> 正文

单元测试之Stub和Mock

简介:
 外部依赖对象
  对于LogAnalyzer对象来说, Service和Email就是两个外部依赖对象. 我们需要自己写Stub和Mock来模拟这两个外部依赖对象。这样我们才能控制他们。
  我们在测试的代码中新建StubWebService和MockEmailService.这两个class分别实现了IWebService和IEmailService.
public class StubWebService : IWebService
{
public void LogError(string message)
{
throw new Exception("StubWebService throw exception");
}
}
public class MockEmailService : IEmailService
{
public string To;
public string From;
public string Subject;
public string Message;
public void SendEmail(string to, string from, string subject, string message)
{
To = to;
From = from;
Subject = subject;
Message = message;
}
}
  工作流程图如下
  最后我们来看看我们的测试代码,
  我们把StubWebService和MockEmailService两个类的实例注入到产品代码中。(因为多态特性嘛)。
  通过控制StubWebService中的LogError方法,抛出一个异常。
  然后判断MockEmailService中的SendEmail方法有没有被调用. 被调用了说明发送了Email(我们不需要真的收到一封邮件,因为SendEmail功能是IEmailService实现的,)
[TestMethod]
public void TestMethod1()
{
StubWebService stubWebService = new StubWebService();
MockEmailService mockEmailSender = new MockEmailService();
LogAnalyzer log = new LogAnalyzer();
log.Emailservice = mockEmailSender;
log.WebService = stubWebService;
// Act
string tooShortFileName = "1.txt";
log.Analyze(tooShortFileName);
// Assert
Assert.AreEqual("to@test.com", mockEmailSender.To);
Assert.AreEqual("from@test.com", mockEmailSender.From);
Assert.AreEqual("WebSerive log error", mockEmailSender.Subject);
}
  Stub和Mock的相同处
  从上面的例子我们可以看出, Stub和Mock都是模拟外部依赖,以便我们能控制。
  Stub 和Mock 的区别
  Stub是完全模拟一个外部依赖, 而Mock用来判断测试通过还是失败
  良好的产品代码才能单元测试

 外部依赖对象
  对于LogAnalyzer对象来说, Service和Email就是两个外部依赖对象. 我们需要自己写Stub和Mock来模拟这两个外部依赖对象。这样我们才能控制他们。
  我们在测试的代码中新建StubWebService和MockEmailService.这两个class分别实现了IWebService和IEmailService.
public class StubWebService : IWebService
{
public void LogError(string message)
{
throw new Exception("StubWebService throw exception");
}
}
public class MockEmailService : IEmailService
{
public string To;
public string From;
public string Subject;
public string Message;
public void SendEmail(string to, string from, string subject, string message)
{
To = to;
From = from;
Subject = subject;
Message = message;
}
}
  工作流程图如下
  最后我们来看看我们的测试代码,
  我们把StubWebService和MockEmailService两个类的实例注入到产品代码中。(因为多态特性嘛)。
  通过控制StubWebService中的LogError方法,抛出一个异常。
  然后判断MockEmailService中的SendEmail方法有没有被调用. 被调用了说明发送了Email(我们不需要真的收到一封邮件,因为SendEmail功能是IEmailService实现的,)
[TestMethod]
public void TestMethod1()
{
StubWebService stubWebService = new StubWebService();
MockEmailService mockEmailSender = new MockEmailService();
LogAnalyzer log = new LogAnalyzer();
log.Emailservice = mockEmailSender;
log.WebService = stubWebService;
// Act
string tooShortFileName = "1.txt";
log.Analyze(tooShortFileName);
// Assert
Assert.AreEqual("to@test.com", mockEmailSender.To);
Assert.AreEqual("from@test.com", mockEmailSender.From);
Assert.AreEqual("WebSerive log error", mockEmailSender.Subject);
}
  Stub和Mock的相同处
  从上面的例子我们可以看出, Stub和Mock都是模拟外部依赖,以便我们能控制。
  Stub 和Mock 的区别
  Stub是完全模拟一个外部依赖, 而Mock用来判断测试通过还是失败
  良好的产品代码才能单元测试
  如果产品代码是下面那样,你就没办法测试了。 因为WebService和EmailService两个类没有继承接口。我们无法把StubWebService和MockEmailService两个类注入到产品代码。
public class LogAnalyzer
{
private WebService webService;
private EmailService emailService;
public WebService WebService
{
get { return webService; }
set { webService = value; }
}
public EmailService Emailservice
{
get { return emailService; }
set { emailService = value; }
}
public void Analyze(string fileName)
{
if (fileName.Length < 8)
{
try
{
WebService.LogError("Filename too short:" + fileName);
}
catch (Exception e)
{
Emailservice.SendEmail("to@test.com", "from@test.com", "WebSerive log error", e.Message);
}
}
}
}
  Mock框架
  其实我们没有必要自己写MockEmailService方法。  已经有现成的Mock框架可以用了, .NET中有Rhino Mock 和 Moq,  这两个框架比较好用


最新内容请见作者的GitHub页:http://qaseven.github.io/

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章