【问题标题】:Mockito and PowerMock MethodNotFoundException being thrown抛出 Mockito 和 PowerMock MethodNotFoundException
【发布时间】:2017-04-20 11:21:46
【问题描述】:

在使用 Powermockito 和 Mockito 为我制作的环绕 Hikari CP 的连接池构建一些简单的单元测试时遇到以下错误。测试的设置如下。令我困惑的是,我有一大堆未显示的单元测试,它们都使用相同的设置和方法通过。只是这个单元测试继续失败并出现该错误。而且不管我在顶部放什么when声明,他们都找不到方法。

org.powermock.reflect.exceptions.MethodNotFoundException: No methods matching the name(s) getColumnCount were found in the class hierarchy of class java.lang.Object.

at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1720)
at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1745)
at org.powermock.reflect.internal.WhiteboxImpl.getBestMethodCandidate(WhiteboxImpl.java:983)
at org.powermock.core.MockGateway$MockInvocation.findMethodToInvoke(MockGateway.java:317)
at org.powermock.core.MockGateway$MockInvocation.init(MockGateway.java:356)
at org.powermock.core.MockGateway$MockInvocation.<init>(MockGateway.java:307)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:142)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:125)
at com.datafiniti.utils.mysqlconnpool.MysqlConnPoolTests.executeStringQuery(MysqlConnPoolTests.java:149)
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:316)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:300)
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:288)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:208)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:147)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:121)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:123)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

这里是单元测试:

@RunWith(PowerMockRunner.class)
public class MysqlConnPoolTests {

private HikariConfig mockHikariConfig;
private HikariDataSource hikariDataSource;

@Before
@PrepareForTest({HikariConfig.class, HikariDataSource.class})
public void beforEachTest() throws Exception {

    // mock the hikari confic used within the connection pool
    mockHikariConfig = PowerMockito.mock(HikariConfig.class);

    // mock hikari config constructor
    PowerMockito.whenNew(HikariConfig.class)
            .withNoArguments()
            .thenReturn(mockHikariConfig);

    // mock hikari config data source setting
    PowerMockito.doNothing().when(mockHikariConfig)
            .setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");

    // mock the hikari data source used within the connection pool
    hikariDataSource = PowerMockito.mock(HikariDataSource.class);

    // mock hikari data source constructor
    PowerMockito.whenNew(HikariDataSource.class)
            .withParameterTypes(HikariConfig.class)
            .withArguments(Mockito.isA(HikariConfig.class))
            .thenReturn(hikariDataSource);
}

@Test
@PrepareForTest({MysqlConnectionPool.class, Connection.class, Statement.class, ResultSet.class, ResultSetMetaData.class})
public void executeStringQuery() throws Exception {
    PowerMockito.spy(MysqlConnectionPool.class);

    Connection mockConnection = Mockito.mock(Connection.class);
    Statement mockStatement = Mockito.mock(Statement.class);
    ResultSet mockResultSet = Mockito.mock(ResultSet.class);
    ResultSetMetaData mockMeta = Mockito.mock(ResultSetMetaData.class);

    Mockito.when(mockMeta.getColumnCount()).thenReturn(1);
    Mockito.when(mockMeta.getColumnLabel(1)).thenReturn("foo");

    Mockito.when(mockResultSet.first()).thenReturn(true);
    Mockito.when(mockResultSet.next()).thenReturn(false);
    Mockito.when(mockResultSet.getString(1)).thenReturn("bar");

    Mockito.when(mockStatement.execute(Mockito.eq("SELECT * FROM table;"))).thenReturn(true);
    Mockito.when(mockStatement.getResultSet()).thenReturn(mockResultSet);

    Mockito.when(mockConnection.createStatement()).thenReturn(mockStatement);

    Mockito.when(hikariDataSource.getConnection()).thenReturn(mockConnection);

    MysqlConnectionPool pool = new MysqlConnectionPool().create();
    List<Map<String, String>> result = pool.executeQuery("SELECT * FROM table;");

    assertEquals(1, result.size());
    assertTrue(result.get(0).containsKey("foo"));
    assertEquals("bar", result.get(0).get("foo"));
}

}

【问题讨论】:

  • 尝试在“public class MysqlConnPoolTests”之前将@PrepareForTest 与您的所有班级一起使用,并在测试之前将其删除。当 PrepareForTest 在测试级别声明时,我有时会看到奇怪的行为。

标签: java unit-testing mockito junit4 powermock


【解决方案1】:

发布答案以防万一其他人看到。将所有版本恢复到 1.6.5 解决了这个问题。

【讨论】:

    【解决方案2】:

    我没有足够的声誉来发表评论,所以很遗憾我正在使用答案空间发表评论。

    Markll,我遇到了类似的问题,这是我的 SO 问题 - org.powermock.reflect.exceptions.MethodNotFoundException: - when mocking java sql classes Mockito.when(mockConnection.createStatement()).thenReturn(mockStatement);为你工作?我的甚至没有超过那个。也许你可以帮助我。我的最新结论是因为 Connection、Statement 和 ResultSets 实际上是接口而不是类,这就是它抛出错误说它在 Object 的层次结构中找不到的原因。

    【讨论】:

    • 感谢您指出,绝对看起来像一个错误。我通过我的进行了一些调试,并意识到它改变了它正在搜索方法的类,从给定的 java.lang.Object 。当然我要的方法不在里面。
    • 是的,这听起来像是一个错误。我建议您可能应该将它写在 PowerMock github repo 的问题部分中,并附上您在调试中观察到的内容。我还没有去调试兔子洞,否则我会自己做的。
    • 似乎已经提交了一个错误 - github.com/powermock/powermock/issues/717
    • 我将我的 powermock 依赖项更改为 1.6.5 并且它有效。您可以尝试检查一下。
    • 成功了!所以这绝对是他们最新版本中的一个错误。
    猜你喜欢
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多