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更适合自己服务器端的测试用例使用

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