我的问题似乎是对模拟的一些误解。测试代码。
public class CallHandler {
private SqlSessionFactory sessionFactory;
public CallHandler() {
String resource = "mybatis/mybatis-config.xml";
Reader reader;
try {
reader = Resources.getResourceAsReader(resource);
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
catch (IOException e) {
e.printStackTrace();
}
}
public String handleRequest(Call call) {
// Some Implementation
}
}
测试类
// I have excluded few unnecessary classes from @PrepareForTest for the post.
@RunWith(PowerMockRunner.class)
@PrepareForTest({SqlSessionFactoryBuilder.class, Resources.class, SqlSessionFactory.class, SqlSession.class})
public class TestCase0 extends TestCase{
private SqlSessionFactory mockedSessionFactory = PowerMock.createMock(SqlSessionFactory.class);
private SqlSession mockedSession = PowerMock.createMock(SqlSession.class);
private CallMapper mockedMapper = PowerMock.createMock(CallMapper.class);
private SqlSessionFactoryBuilder mockedSqlSessionFactoryBuilder= PowerMock.createMock(SqlSessionFactoryBuilder.class);
// Others
@Before
public void setUp() {
}
@Test
public void test0 () throws Exception {
mockStatic(CallMapper.class);
mockStatic(SqlSessionFactoryBuilder.class);
mockStatic(Resources.class);
expect(Resources.getResourceAsReader("mybatis/mybatis-config.xml")).andReturn(mockedReader); expectNew(SqlSessionFactoryBuilder.class).andReturn(mockedSqlSessionFactoryBuilder); expect(mockedSqlSessionFactoryBuilder.build(mockedReader)).andReturn(mockedSessionFactory);
expect(mockedSessionFactory.openSession()).andReturn(mockedSession);
// Few more expectations
replayAll();
assertThat(RESULT0).isEqualTo((new CallHandler()).handleRequest(call));
verifyAll();
}
}
在新的 SqlSessionFactoryBuilder
上调用构建的模拟似乎没有生效,因为原始的 build()
被调用,因此出现错误。堆栈跟踪
java.lang.AssertionError:
Unexpected method call Reader.close();
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:44)
at org.powermock.api.easymock.internal.invocationcontrol.EasyMockMethodInvocationControl.invoke(EasyMockMethodInvocationControl.java:91)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:105)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:168)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:58)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:38)
at com.kwench.integration.ivr.CallHandler.<init>(CallHandler.java:48)
at in.kwench.integration.ivr.TestCase0.test0(TestCase0.java:131)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
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:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
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:282)
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:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
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:118)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:104)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
最佳答案
如果没有您正在测试的代码的完整示例和测试类本身,很难说出您的问题可能出现在哪里。
话虽如此,我猜你的问题是你没有用静态方法准备类。这些需要在测试类开始时在 @PrepareForTest 注释中提供。
PowerMock 的文档提供了以下有关模拟静态方法的提示。我猜你错过了第 2 点。Here is the source for this documentation
Mocking static methods
Quick summary
- Use the @RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
- Use the @PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case.
- Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class.
- Use PowerMock.replay(ClassThatContainsStaticMethod.class) to change the class to replay mode.
- Use PowerMock.verify(ClassThatContainsStaticMethod.class) to change the class to verify mode.
您还模拟了 SqlSessionFactoryBuilder
的构造函数调用,因此您也需要考虑这方面的提示。 Here is the documentation for this
Mock construction of new objects
Quick summary
- Use the @RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
- Use the @PrepareForTest(ClassThatCreatesTheNewInstance.class) annotation at the class-level of the test case.
- Use PowerMock.createMock(NewInstanceClass.class) to create a mock object of the class that should be constructed (let's call it mockObject).
- Use PowerMock.expectNew(NewInstanceClass.class).andReturn(mockObject) to expect a new construction of an object of type NewInstanceClass.class but instead return the mock object.
- Use PowerMock.replay(mockObject, NewInstanceClass.class) to change the mock object and class to replay mode, alternatively use the PowerMock.replayAll() method.
- Use PowerMock.verify(mockObject, NewInstanceClass.class) to change the mock object and class to verify mode, alternatively use the PowerMock.verifyAll() method.
考虑到这些提示,我针对您提供的您尝试测试的方法生成了以下测试方法。这个测试顺利通过。
@RunWith(PowerMockRunner.class)
@PrepareForTest({CallHandler.class, SqlSessionFactoryBuilder.class, Resources.class})
public class CallHandlerTest {
private static final String RESULT0 = "";
@Test
public void test0 () throws Exception {
final Reader mockedReader = EasyMock.createMock(Reader.class);
final SqlSessionFactoryBuilder mockedSqlSessionFactoryBuilder = EasyMock.createMock(SqlSessionFactoryBuilder.class);
final SqlSessionFactory mockedSessionFactory = EasyMock.createMock(SqlSessionFactory.class);
PowerMock.mockStatic(SqlSessionFactoryBuilder.class);
PowerMock.mockStatic(Resources.class);
PowerMock.expectNew(SqlSessionFactoryBuilder.class).andReturn(mockedSqlSessionFactoryBuilder);
EasyMock.expect(Resources.getResourceAsReader("mybatis/mybatis-config.xml")).andReturn(mockedReader);
EasyMock.expect(mockedSqlSessionFactoryBuilder.build(mockedReader)).andReturn(mockedSessionFactory);
PowerMock.replayAll();
assertThat(RESULT0).isEqualTo((new CallHandler()).handleRequest(new Call()));
PowerMock.verifyAll();
}
}
关于java - 使用 PowerMock- EasyMock 时意外的方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24361495/