背景
本文假設你對TDD、Stub和Mock已經有了初步的認識,本文簡單解釋一下stub和mock的區別和使用場景,先看看他們之間的關系:
由上圖可以知道mock框架可以非常容易的開發stub和mock,但是stub框架想要提高mock機制就要靠自己擴展了。
Stub
stub存在的意圖是為了讓測試對象可以正常的執行,其實現一般會硬編碼一些輸入和輸出,下面的代碼使用了MS自帶的Fake和Shim來實現stub。
Fake實現
1 using System; 2 using Microsoft.VisualStudio.TestTools.UnitTesting; 3 4 using TDDStudy.Library.WhatIsStub; 5 using TDDStudy.Library.WhatIsStub.Fakes; 6 7 namespace TDDStudy.WhatIsStub 8 { 9 [TestClass] 10 public class WhatIsStubTest 11 { 12 [TestMethod] 13 public void Stub_Test() 14 { 15 var domainService = new DomainService(CreateStubDependencyService()); 16 domainService.Task(); 17 } 18 19 private IDependencyService CreateStubDependencyService() 20 { 21 return new StubIDependencyService 22 { 23 OtherTask = () => { } 24 }; 25 } 26 } 27 }
Shim實現
1 using System; 2 using Microsoft.VisualStudio.TestTools.UnitTesting; 3 using Microsoft.QualityTools.Testing.Fakes; 4 5 using TDDStudy.Library.WhatIsShim; 6 using TDDStudy.Library.WhatIsShim.Fakes; 7 8 namespace TDDStudy.WhatIsShim 9 { 10 [TestClass] 11 public class WhatIsStubTest 12 { 13 [TestMethod] 14 public void Shim_Test() 15 { 16 using (ShimsContext.Create()) 17 { 18 var domainService = new DomainService(CreateShimDependencyService()); 19 domainService.Task(); 20 } 21 } 22 23 private DependencyService CreateShimDependencyService() 24 { 25 return new ShimDependencyService 26 { 27 OtherTask = () => { } 28 }; 29 } 30 } 31 }
備注:微軟的Fake適合接口、保護虛方法的類,Shim適合其它類(封閉的、非虛的)。
Mock
mock除了保證stub的功能之外,還可深入的模擬對象之間的交互方式,如:調用了幾次、在某種情況下是否會拋出異常,下面的代碼使用了moq來實現mock。
moq實現
1 using System; 2 using Microsoft.VisualStudio.TestTools.UnitTesting; 3 4 using Moq; 5 using TDDStudy.Library.WhatIsMock; 6 7 namespace TDDStudy.WhatIsMock 8 { 9 [TestClass] 10 public class WhatIsStubTest 11 { 12 [TestMethod] 13 public void Mock_Test() 14 { 15 var mock = CreateMockDependencyService(); 16 17 var domainService = new DomainService(mock.Object); 18 domainService.Task(); 19 20 mock.Verify(x => x.OtherTask(), Times.AtMostOnce); 21 } 22 23 private Mock<IDependencyService> CreateMockDependencyService() 24 { 25 return new Mock<IDependencyService>(); 26 } 27 } 28 }
備注:mock是一種功能豐富的stub。
備注
我目前只使用MS的Fake,感覺夠了。