JUnit - The first sight

JUnit是一個Java語言的單元測試框架,目前主流為JUnit4 與JUnit5

junit5功能多又比較全面,因為junit5有向下相容junit4所以常常會看到混著寫的情況
可以觀察annotation, method的package,以下則是junit 5
org.junit.jupiter.api.

若是以下的則是junit 4
org.junit.

由於mocking的物件會橫跨至其他class,因此為了做mock session延展至在unit test階段,可以initMocks
@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}


Getting start with @Mock, @Spy, @Captor and @InjectMocks
以上都是Mockito的annotation
不同的annotations 使用方式來啟動mockito test
  1. MoclitoJUnitRunner 就是最基本的JUnit測試
@RunWith(MockitoJUnitRunner.class)
public class MockitoAnnotationTest {
    ...
}
  1. MockitoAnnotations.initMocks() 以programming的方式透過它來啟動Mockito
@Before
public void init() {
    MockitoAnnotations.initMocks(this);
}
  1. MockitoJUnit.rule()  (比較少看到...)
public class MockitoInitWithMockitoJUnitRuleUnitTest {

@Rule
    public MockitoRule initRule = MockitoJUnit.rule();

    ...
}

@Mock Annotation
最常見到到的Annotation, 用@Mock 建立/注入mocked instances
在沒有annotation的時候則需要自己寫Mockito instance
List mockList = Mockito.mock(ArrayList.class);
vs
@Mock
List<String> mockedList;

@Spy annotation 相較於Mock是產生假的實例,spy就是去監視存在的instance
List<String> spyList = Mockito.spy(new ArrayList<String>());
vs
@Spy
List<String> spiedList = new ArrayList<String>();
所以能夠用真實的method來操作instance,也能用Stubbed method去模擬回傳情境

@Captor Annotation 產生參數捕獲器 ArgumentCaptor instance
攔截讓mock的物件執行method的參數
List mockList = Mockito.mock(List.class);
ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);
List mockList = Mockito.mock(List.class);
ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);

mockList.add("one");
Mockito.verify(mockList).add(arg.capture());

assertEquals("one", arg.getValue());
vs
@Mock
List mockedList;
@Captor
ArgumentCaptor argCaptor;
mockedList.add("one");
Mockito.verify(mockedList).add(argCaptor.capture());

assertEquals("one", argCaptor.getValue());

@InjectMocks Annotation 自動注入模擬資料,也就是能將@InhjectMocks的物件去注入 @Mock的模擬資料(這也說明為什麼你不能把Autowired的物件丟進去了
@Mock
Map<String, String> wordMap;

@InjectMocks
MyDictionary dic = new MyDictionary();

@Test
public void whenUseInjectMocksAnnotation_thenCorrect() {
    Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning");

    assertEquals("aMeaning", dic.getMeaning("aWord"));

Mockito Annotation又是來減少code量,並且易讀性高。
要注入@Spy 跟 @Mock, @InjectMocks 是必須要有的


@Mock 與 @MockBean 不同?

運用 Mockito.mock 建立一個物件並設定在call method或verify後回傳特定值
在class上用junit runner annotation
@RunWith(MockitoJUnitRunner.class)
Spring Boot's @MockBean annotation 是mock Spring application context. (Application context是Spring的應用程式)
也就可以做到模擬在call method或verify後回傳的值
在class上用spring runner annotation
@RunWith(SpringRunner.class)


References:


留言

這個網誌中的熱門文章

[專案] 銀行端末系統

如何在MacOS 中自由切換不同Python版本 - pyenv + virtualenv

用 C# 控制 Win7 輸入法