PowerMock和JMockit的使用與對比

PowerMock的使用

之所以提到PowerMock而不是Mock,是因爲自己服務器端的配置數據獲取的方法是靜態方法,如果使用mock方式來模擬數據,只有PowerMock支持Mock靜態方法,Mock不支持。

引入PowerMock

<dependency>
	<groupId>org.powermock</groupId>
	<artifactId>powermock-module-junit4</artifactId>
	<version>2.0.0</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.powermock</groupId>
	<artifactId>powermock-api-mockito2</artifactId>
	<version>2.0.0</version>
	<scope>test</scope>
</dependency>

編寫測試用例

@RunWith(PowerMockRunner.class) //該註解表示當前測試類的運行模式爲PowerMock,不加這個註解,PowerMock不生效
@PrepareForTest({ NumericService.class }) //該註解表示要在當前測試類中進行Mock的類
@PowerMockIgnore({ "javax.management.*", "javax.crypto.*", "sun.security.ssl.*", "sun.security.jca.*", "javax.net.*" })//本行註解要求PowerMock使用自定義ClassLoader加載時,忽略一部分底層包,否則會出現各種“class not cast to”之類的諸多報錯
public class PowerMockTest {
	@Test
	public void test() throws Exception {
		long time = System.currentTimeMillis();
		TestUtility.init();
		System.out.println(System.currentTimeMillis() - time);
		try {
			NumericService.getNumericById(TabShop.class, "forTest");
			fail();
		} catch (Exception e) {
		}
		PowerMockito.mockStatic(NumericService.class);
		PowerMockito.when(NumericService.getNumericById(TabShop.class, "forTest")).thenReturn(null);
		System.out.println(NumericService.getNumericById(TabShop.class, "forTest"));
	}

}

運行代碼查看運行效果,已經是否Mock成功。

17:11:54.117 [main] ERROR com.***.utli.TestUtility - NCC Server started…
17:11:54.129 [main] INFO com.***.gs.common.JobThreadPoolExecutor - init corePoolSize:10
64269
null
17:11:54.931 [Thread-4] ERROR gamebase.base.server.BaseServer - Execute ShutdownHook Start
17:11:54.932 [Thread-4] ERROR gamebase.base.server.BaseServer - Execute ShutdownHook End

可見PowerMock已經成功將 NumericService.getNumericById(TabShop.class, "forTest") Mock住,並將返回值設置成null。
但是,注意在null值前面的數值,表示TestUtility.init();運行的時間,高達64秒,太耗時了,這是因爲在TestUtility.init();中初始化了很多東西,PowerMock下運行時導致性能嚴重下降,基於這個原因,後來又找到JMock來實現對數據獲取的模擬。

JMockit的使用

引入JMockit

<!-- 先聲明jmockit的依賴 -->
<dependency>
	<groupId>org.jmockit</groupId>
	<artifactId>jmockit</artifactId>
	<version>1.36</version>
	<scope>test</scope>
	</dependency>
<!-- 再聲明junit的依賴 -->

編寫測試用例

public class JMockTest {
	@Test
	public void testExpectations() {
		try {
			NumericService.getNumericById(TabShop.class, "2");
			fail();
		} catch (Exception e) {
		}
		new Expectations(NumericService.class) {
			{
				NumericService.getNumericById(TabShop.class, "2");
				result = null;
			}
		};
		System.out.println(NumericService.getNumericById(TabShop.class, "2"));
	}

	@Test
	public void testMockUp() {
		try {
			NumericService.getNumericById(TabShop.class, "1");
			fail();
		} catch (Exception e) {
		}
		new MockUp<NumericService>() {
			@Mock
			public <T> T getNumericById(Class<T> clz, String numericId) {
				return null;
			}
		};
		System.out.println(NumericService.getNumericById(TabShop.class, "1"));
	}
}

ExpectationsMockUp的測試用例都能跑通,在這裏不在貼上結果。不過可以看到,JMockit的使用比起PowerMock更加輕量級,不需要對類進行整個註解,而是在單個測試用例中使用new的方式進行修改。

比較

比較項目 PowerMock JMockit
使用便捷度 需要對整個測試類做註解 在單個測試用例中使用即可
調用Mock後的方法10000遍消耗的時間(毫秒) 1278 483
準確度 目前所知,PowerMock後的靜態方法所有返回值都是Mock的值 支持指定參數的指定返回值,不符合參數值的調用不走Mock
生命週期 從類的加載到結束 從調用new到當前測試用例結束
機制 自定義ClassLoader加載測試類,並處理類中所有的引用,包括底層甚至JDK部分代碼 通過字節碼處理,生成替換類,不對其他引用出處理

通過以上比較,目前確認JMockit更適合自己服務器端的測試用例使用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章