Spring中如何使用Mockito做單元測試
阿新 • • 發佈:2019-02-19
在Spring環境下做單元測試常常遇到很多問題,Controller層還好說,Spring本身提供了很多方法來支援,這個可以看我的另一篇文章
但是在服務層和持久層,如果是使用註解注入的方式來設計的話,用Mock來替換真實的注入類就很麻煩了,還好我們有Mockito框架。但一段程式碼,你會發現它比easyMock好用多了
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath*:application-context-test.xml" }) public class RouteServiceTestCase{ @InjectMocks @Autowired private IRouteService service; @Mock private IRouteMatrixDataProvider provider; @Before public void myBefore() { MockitoAnnotations.initMocks(this); } @Test public void testGetAirlineCode() { RouteMatrix rm = new RouteMatrix(); rm.setAirlineCode("kkk"); Mockito.when(this.provider.getRevenueRoute("HKG", "AMM", true)).thenReturn(rm); String code = this.service.getAirlineCode("HKG", "AMM", this.brand, this.cInfo, true); Assert.assertNotNull(code); Assert.assertEquals("kkk", code); code = this.service.getAirlineCode("HKG", "KKK", this.brand, this.cInfo, true); Assert.assertNull(code); } @Test public void testGetAirlineCode2() { String code = this.service.getAirlineCode("HKG", "AMM", this.brand, this.cInfo, true); Assert.assertNotNull(code); Assert.assertEquals("kkk", code); } }
@Spy
@Autowired
private IRouteMatrixDataProvider provider;
service
被標記了 @InjectMocks , 在 myBefore方法中 執行 MockitoAnnotations.initMocks(this); 的時候,會將標記了 @Mock 或 @Spy 的屬性注入到 service 中。
如果是 @Mock, 那就是通常的方式,service裡面的provider完全被Mock例項替換,所有的呼叫都是針對Mock生成類的。
如果是 @Autowired 加 @Spy , 那麼對於定製了返回值的會呼叫 Mock例項,否則會呼叫真實注入的屬性,但是這裡有一個限制,如果是代理類會報錯,比如Spring 的AOP代理。
對於AOP的代理類,如果想一部分用Mock,一部分用真實的例項,感覺目前是有些困難,暫時想到的辦法就是寫兩個測試類,一個注入真實屬性,一個注入mock屬性。
方法呼叫時,如果不想指定一個明確的引數,就可以用下面這樣的寫法來表示任意的引數。
Mockito.when(this.provider.getRevenueRoute(Matchers.anyString(), Matchers.anyString(), Matchers.anyBoolean()))
.thenReturn(rm);
但是這裡也有一個限制就是,如果有一個引數使用了any***(),則所有的引數都必需使用這種方式,不能像下面這樣寫
Mockito.when(this.provider.getRevenueRoute(Matchers.anyString(), Matchers.anyString(), true))