在JUnit 4測試時如果Mockito要對靜態方法(static method),final
類別或方法,private
方法等做mock,必須搭配PowerMock使用。
注意JUnit 4和JUnit 5設定上有不少差異,本範例僅適用於JUnit 4.4以上,Mockito 2版本。
在Maven的pom.xml
的<dependencies>
中加入以下依賴。
<!-- JUnit 4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Mockito -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.27.0</version>
<scope>test</scope>
</dependency>
<!-- PowerMock -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
因為使用的JUnit 4版本為4.4以上,Mockito版本為2以上,所以PowerMock的設定如上,請參考Maven setup for the Mockito 2.x。
以下分別為要被測式的方法DemoService.add()
及被測式的方法中所依賴的靜態方法DemoUtil.add()
。
DemoService
public class DemoService {
// 要被測試的方法
public int add(int x, int y) {
return DemoUtil.add(x, y);
}
}
DemoUtil
是一個Helper工具類別,因此類別和方法都宣告為final
,PowerMock仍可對其mock。
DemoUtil
public final class DemoUtil {
private DemoUtil() {
}
// 被DemoService.add()依賴的靜態方法
public static final int add(int x, int y) {
return x + y;
}
}
下面則是負責對DemoService
進行測試的測試類別DemoServiceTest
。
在測試類別上掛上@RunWith(PowerMockRunner.class)
及@PrepareForTest({DemoUtil.class})
。@PrepareForTest
的值為要被Mock的靜態方法的類別,也就是DemoUtil.class
。
然後在測試方法testAddGiven1And2()
中要呼叫PowerMockito.mockStatic(DemoUtil.class);
來告訴PowerMock傳入的DemoUtil.class
的所有靜態方法都要被mock。
DemoServiceTest
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.abc.board.util.DemoUtil;
@RunWith(PowerMockRunner.class) // 必須使用PowerMockRunner
@PrepareForTest({DemoUtil.class}) // 告訴PowerMock準備要被Mock的靜態類別,可以設定多個。
public class DemoServiceTest {
private DemoService demoSerivce = new DemoService();
// 負責測試DemoService.add()
@Test
public void testAddGiven1And2() {
int x = 1; int y = 2;
int expected = x + y;
PowerMockito.mockStatic(DemoUtil.class); // 告訴PowerMock DemoUtil中的靜態方法都要被Mock
Mockito.when(DemoUtil.add(x, y)).thenReturn(expected);
int actual = demoSerivce.add(x, y);
Assert.assertEquals(expected, actual);
}
}
因為DemoUtil.add()
是static
final
方法,所以必須透過PowerMock才能對其進行Mock的動作。
PowerMock是透過其類別載入器(ClassLoader)及直接操作位元組碼(bytecode)來達到以上目的。
參考:
沒有留言:
張貼留言