Mockito
使用 Mockito 生成 Mock 物件
Mockito 是一個流行 mock 框架,可以和JUnit結合起來使用。Mockito 允許你建立和配置 mock 物件。使用Mockito可以明顯的簡化對外部依賴的測試類的開發。
一般使用 Mockito 需要執行下面三步
模擬並替換測試程式碼中外部依賴。
執行測試程式碼
驗證測試程式碼是否被正確的執行
https://www.itread01.com/content/1549761155.html
VVV
https://kucw.github.io/blog/2020/2/spring-unit-test-mockito/
code:
@Component
public class UserService {
@Autowired
private UserDao userDao;
public User getUserById(Integer id) {
return userDao.getUserById(id);
}
public Integer insertUser(User user) {
return userDao.insertUser(user);
}
}
Junit mockito
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
//先普通的注入一個userService bean
@Autowired
private UserService userService;
@Test
public void getUserById() throws Exception {
//普通的使用userService,他裡面會再去call userDao取得DB的data
User user = userService.getUserById(1);
//檢查結果
Assert.assertNotNull(user);
Assert.assertEquals(user.getId(), new Integer(1));
Assert.assertEquals(user.getName(), "John");
}
}
但是如果 userDao 還沒寫好,又想先測 userService 的話,就需要使用 Mockito 去模擬一個假的 userDao 出來
使用方法是在 userDao 上加上一個 @MockBean
注解,當 userDao 被加上這個注解之後,表示 Mockito 會幫我們創建一個假的 mock 對象,替換掉 Spring 中已存在的那個真實的 userDao bean,也就是說,注入進 userService 的 userDao bean,已經被我們替換成假的 mock 對象了,所以當我們再次調用 userService 的方法時,會去調用的實際上是 mock userDao bean 的方法,而不是真實的 userDao bean
當我們創建了一個假的 userDao 後,我們需要為這個 mock userDao 自定義方法的返回值,這裡有一個公式用法,下面這段 code 的意思為,當調用了某個 mock 對象的方法時,就回傳我們想要的自定義結果
Mockito.when( 對象.方法名() ).thenReturn( 自定義結果 )
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@MockBean
private UserDao userDao;
@Test
public void getUserById() throws Exception {
// 定義當調用mock userDao的getUserById()方法,並且參數為3時,就返回id為200、name為I'm mock3的user對象
Mockito.when(userDao.getUserById(3)).thenReturn(new User(200, "I'm mock 3"));
// 返回的會是名字為I'm mock 3的user對象
User user = userService.getUserById(3);
Assert.assertNotNull(user);
Assert.assertEquals(user.getId(), new Integer(200));
Assert.assertEquals(user.getName(), "I'm mock 3");
}
}
verify 系列方法
檢查調用 userService 的 getUserById()、且參數為3的次數是否為1次
Mockito.verify(userService, Mockito.times(1)).getUserById(Mockito.eq(3));
驗證調用順序,驗證 userService 是否先調用 getUserById() 兩次,並且第一次的參數是 3、第二次的參數是 5,然後才調用insertUser() 方法
InOrder inOrder = Mockito.inOrder(userService);
inOrder.verify(userService).getUserById(3);
inOrder.verify(userService).getUserById(5);
inOrder.verify(userService).insertUser(Mockito.any(User.class));
4. Mockito 的限制
上述就是 Mockito 的 mock 對象使用方法,不過當使用 Mockito 在 mock 對象時,有一些限制需要遵守
- 不能 mock 靜態方法
- 不能 mock private 方法
- 不能 mock final class
因此在寫 code 時,需要做良好的功能拆分,才能夠使用 Mockito 的 mock 技術,幫助我們降低測試時 bean 的 dependency
https://www.infoworld.com/article/3537563/junit-5-tutorial-part-1-unit-testing-with-junit-5-mockito-and-hamcrest.html?page=3
留言
張貼留言