单元测试Mock使用 Microsoft Fakes 讲解
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
在编写单元测试时,我们会遇到不同的外部依赖项,大体上可以分为两类:
- 依赖于接口或抽象类
- 依赖于具体类
我们将使用 Microsoft Fakes 分别对两种条件下的依赖项进行隔离。
依赖于接口或抽象类
生活不总是那么美好,当然不是所有代码都会遵循控制反转的原则。很多时候,我们仍然需要使用具体类。
比如,在如下的代码中,OrderRepository 中的 Add 方法直接构建一个 EmailSender ,然后调用其 SendEmail 方法来发送邮件。
1 public class Order 2 { 3 public long Id { get; set; } 4 public override string ToString() 5 { 6 return Id.ToString(); 7 } 8 } 9 10 public interface IOrderRepository 11 { 12 Order Add(Order order); 13 } 14 15 public class EmailSender : IEmailSender 16 { 17 public bool SendEmail(string content) 18 { 19 return true; 20 } 21 } 22 23 public class OrderRepository : IOrderRepository 24 { 25 public OrderRepository() 26 { 27 } 28 29 public Order Add(Order order) 30 { 31 IEmailSender emailSender = new EmailSender(); 32 emailSender.SendEmail(order.ToString()); 33 return order; 34 } 35 }
现在,我们已经没有接口或者抽象类可用于模拟了,所以 Stub 在此种条件下也失去了作用。此时,Shim 上场了。Shim 是运行时方法拦截器,功能更加强大。通过 Shim 我们可以为任意类的方法或属性提供我们自己的实现。
1 [TestMethod] 2 public void TestOrderRepositoryWhenAddOrderThenShouldSendEmail() 3 { 4 // Arrange 5 bool isEmailSent = false; 6 7 using (ShimsContext.Create()) 8 { 9 ShimEmailSender.AllInstances.SendEmailString = (@this, content) => 10 { 11 isEmailSent = true; 12 return true; 13 }; 14 15 // Act 16 OrderRepository repository = new OrderRepository(); 17 Order order = new Order() { Id = 123 }; 18 repository.Add(order); 19 } 20 21 // Assert 22 Assert.IsTrue(isEmailSent); 23 }
使用 Shim 时,需要先为其指定上下文范围,通过 ShimsContext.Create() 来创建。
通常,如果遇到使用 Shim 的情况,则说明代码或许写的有些问题,没有遵循控制反转原则等。
使用 Shim 来控制系统类
- Isolating Code Under Test with Microsoft Fakes
- Better Unit Testing with Microsoft Fakes
- Visual studio 2012 Fakes
- Using shims to isolate your application from other assemblies for unit testing
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
出处:https://www.cnblogs.com/gaochundong/p/unit_test_with_microsoft_fakes.html