单元测试之Stub和Mock

    xiaoxiao2022-07-16  167

    外部依赖对象   对于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/ 相关资源:敏捷开发V1.0.pptx
    最新回复(0)