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





留言

這個網誌中的熱門文章

考績被打差了 輕率離職會更傷

Arrays - DS (Reverse array) [Easy]

WireMock