Mockito和PowerMock用法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mockito和PowerMock用法相关的知识,希望对你有一定的参考价值。
参考技术A PowerMock是Java开发中的一种Mock框架,用于 单元模块测试 。当你想要测试一个service接口,但service需要经过防火墙访问,防火墙不能为你打开或者你需要认证才能访问。遇到这样情况时,你可以在你能访问的地方使用MockService替代,模拟实现获取数据。
PowerMock可以实现完成对 private/static/fina l方法的Mock(模拟),而Mockito可以对普通的方法进行Mock,如:public等。
Demo演示
PowerMock基于Mockito开发,起语法规则与Mockito一致,主要区别在于使用方面,以实现完成对 private/static/fina l等方法(也支持mock的对象是在方法内部new出来的)的Mock(模拟)。具体事例如下:
1、添加依赖
我们可以使用Mockito和PowerMock出售junit测试类
我有一个只有一个method
的java类,在我创建object for another class
的方法中,所以我使用的是PowerMockito.whenNew(fullyQualifiedClassName).withAnyArguments().thenReturn(mockObject);
。在同样的方法中,我必须模拟另一个method(non-static)
所以我必须在这里使用Mockito
像Mockito.when(mockObject.method1(1000)).thenReturn(createdObject);//showing error here
。我收到的错误如下
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.tocassandra.DMCassandraTest.test(DMCassandraTest.java:38)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
at com.tocassandra.DMCassandraTest.test(DMCassandraTest.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:326)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:298)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:218)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:160)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:134)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:136)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:117)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
我用注释宣布Junit Test class
@RunWith(PowerMockRunner.class)
@PrepareForTest({NewObjectClass.class})
示例代码: -
原始方法如下所示
public static void insertData(String name) throws Exception {
ObjectMapper mapper = new ObjectMapper();
SampleA sample = new SampleA("args1","arg2",4);
sample.subscribe(name); //its a void method
logger.info("subscibed to the topic {}", ConsumerTopicName);
cluster = Cluster.builder().addContactPoints(CASSANDRA_CONNECTION_HOST.split(",")).build();
session = cluster.connect(KEYSPACE);
try {
while (true) {
try {
SampleRecords records = sample.getRecords("argValue");
for (Record record : records) {
A a = mapper.readValue(record.value(), A.class);
dao.insertData(session, a);
}
} catch (Exception ex) {
logger.error("Exception while reading data from kafka", ex);
}
}
} finally {
consumer.close();
}
}
测试类: -
@RunWith(PowerMockRunner.class)
@PrepareForTest({SampleA.class})
public class DMCassandraTest {
SampleA sample = Mockito.mock(SampleA.class);
@Test
public void test() throws Exception{
String name = "test";
PowerMockito.whenNew("org.companny.SampleA").withAnyArguments().thenReturn(sample);
Mockito.doAnswer(new Answer(){
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
sample.subscribe(name);
return null;
}
}).when(SampleA.class);
// Above code is to mock void subscribe method in insertData, even I am
// not sure whther it works or not
SampleRecords records = new SampleReccords();
// setting values to records
Mockito.when(sample.getRecords("argdValue")).thenReturn(records);
insertToCassandra.insertData(name);
}
}
主要问题是这个块:
Mockito.doAnswer(new Answer(){
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
sample.subscribe(name);
return null;
}
}).when(SampleA.class);
Mockito问你,“什么时候?”您没有指定Mockito的模拟应该回复的时间。从逻辑上看,似乎你想在subscribe
之后这样做。
但是,说实话,我没有看到很多机会(或理由)嘲笑。您获得的实例具体定义,无法轻松注入以增加其值的差异。我的建议是不要嘲笑这些,直到你可以在某处注入SampleA
,这样添加模拟比依赖PowerMockito更麻烦。
以上是关于Mockito和PowerMock用法的主要内容,如果未能解决你的问题,请参考以下文章
一文教会你mock(Mockito和PowerMock双剑合璧)
我们可以使用Mockito和PowerMock出售junit测试类