前言
在Testing: 隔離框架(Isolation framework) - 使用Mockito建立測試替身一文中,我們練習如何使用Mockito框架模擬測試替身後,接著要來學習PowerMock的框架,輔助我們測試與驗證靜態方法。PowerMock的使用
PowerMock使用起來相當簡單,首先我們在gradle中引用PowerMock,程式碼如下。dependencies {
testCompile 'org.powermock:powermock-module-junit4:1.6.2'
testCompile 'org.powermock:powermock-api-mockito:1.6.2'
}
以RegisterManager為例
- RegisterManager物件
public class RegisterManager {
private IEmailRegister emailRegister;
private IMobileRegister mobileRegister;
public RegisterManager(IEmailRegister emailRegister, IMobileRegister mobileRegister) {
this.emailRegister = emailRegister;
this.mobileRegister = mobileRegister;
}
public void register(String content) {
if (RegistrationFormat.checkFormat(content)) {
this.emailRegister.emailRegister();
} else {
this.mobileRegister.mobileRegister();
}
}
}
- RegistrationFormat類別
public class RegistrationFormat {
public static boolean checkFormat(String content) {
boolean isEmail = false;
if (content.contains("@")) {
return isEmail;
}
return !isEmail;
}
}
- IEmailRegister介面
public interface IEmailRegister {
void emailRegister();
}
- IMobileRegister介面
public interface IMobileRegister {
void mobileRegister();
}
RegisterManager的功能相當簡單,它提供了Email與Mobile這兩種註冊方法,透過RegistrationFormat類別的靜態方法檢查,若是屬於Email格式,就使用Email註冊,Mobile註冊則反之,接著我們來看測試程式。
@RunWith(PowerMockRunner.class)
@PrepareForTest(RegistrationFormat.class)
public class RegisterManagerWithPowerMockitoTest {
@Test
public void testRegisterIsEmail() throws Exception {
// Arrange
IEmailRegister mockEmailRegister = Mockito.mock(IEmailRegister.class);
IMobileRegister mockMobileRegister = Mockito.mock(IMobileRegister.class);
PowerMockito.mockStatic(RegistrationFormat.class);
Mockito.when(RegistrationFormat.checkFormat(Mockito.anyString())).thenReturn(true);
RegisterManager registerManager = new RegisterManager(mockEmailRegister, mockMobileRegister);
// Act
registerManager.register(Mockito.anyString());
// Assert
Mockito.verify(mockEmailRegister).emailRegister();
}
@Test
public void testRegisterIsMobile() throws Exception {
// Arrange
IEmailRegister mockEmailRegister = Mockito.mock(IEmailRegister.class);
IMobileRegister mockMobileRegister = Mockito.mock(IMobileRegister.class);
PowerMockito.mockStatic(RegistrationFormat.class);
Mockito.when(RegistrationFormat.checkFormat(Mockito.anyString())).thenReturn(false);
RegisterManager registerManager = new RegisterManager(mockEmailRegister, mockMobileRegister);
// Act
registerManager.register(Mockito.anyString());
// Assert
Mockito.verify(mockMobileRegister).mobileRegister();
}
@Test
public void testRegistrationFormatCheckFormatIsCalled() throws Exception {
// Arrange
IEmailRegister mockEmailRegister = Mockito.mock(IEmailRegister.class);
IMobileRegister mockMobileRegister = Mockito.mock(IMobileRegister.class);
PowerMockito.mockStatic(RegistrationFormat.class);
Mockito.when(RegistrationFormat.checkFormat(Mockito.anyString())).thenReturn(false);
RegisterManager registerManager = new RegisterManager(mockEmailRegister, mockMobileRegister);
// Act
registerManager.register(Mockito.anyString());
// Assert
PowerMockito.verifyStatic(Mockito.times(1));
RegistrationFormat.checkFormat(Mockito.anyString());
}
}
要使用PowerMock首先要依循以下方式:
- @RunWith(PowerMockRunner.class): 使用@RunWith的Annotation,並且類別指定PowerMockRunner.class。
- @PrepareForTest(RegistrationFormat.class): 使用@PrepareForTest的Annotation,聲明要Mock的靜態方法類別,這邊指定RegistrationFormat.class。
- PowerMockito.mockStatic(RegistrationFormat.class): 使用mockStatic方法Mock靜態類別
接著預期我們的測試程式,可以使用下列方法。
- Mockito.when(RegistrationFormat.checkFormat(Mockito.anyString())).thenReturn(false): 如同Mockito的方法,我們指定RegistrationFormat使用checkFormat的靜態方法時,所欲回傳的值。
- PowerMockito.verifyStatic(Mockito.times(1)): 先斷言該靜態方法執行的次數。
- RegistrationFormat.checkFormat(Mockito.anyString()): 實際執行該方法。
這邊需要注意的是,PowerMock斷言的方式有些奇怪,要先斷言再執行呼叫,值得注意喔!這邊也能順利通過測試,如下圖。
沒有留言:
張貼留言