我写了一个工厂来产生java.sql.Connection对象:

public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory {

    @Override public Connection getConnection() {
        try {
            return DriverManager.getConnection(...);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

我想验证传递给DriverManager的参数。getConnection,但我不知道如何模拟静态方法。我的测试用例使用JUnit 4和Mockito。是否有一个好的方法来模拟/验证这个特定的用例?


当前回答

你可以做一点重构:

public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory {

    @Override public Connection getConnection() {
        try {
            return _getConnection(...some params...);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    //method to forward parameters, enabling mocking, extension, etc
    Connection _getConnection(...some params...) throws SQLException {
        return DriverManager.getConnection(...some params...);
    }
}

然后你可以扩展你的MySQLDatabaseConnectionFactory类来返回一个模拟的连接,对参数进行断言等等。

扩展类可以驻留在测试用例中,如果它位于相同的包中(我鼓励您这样做)

public class MockedConnectionFactory extends MySQLDatabaseConnectionFactory {

    Connection _getConnection(...some params...) throws SQLException {
        if (some param != something) throw new InvalidParameterException();

        //consider mocking some methods with when(yourMock.something()).thenReturn(value)
        return Mockito.mock(Connection.class);
    }
}

其他回答

要模拟静态方法,您应该使用Powermock查看: https://github.com/powermock/powermock/wiki/MockStatic。 Mockito不提供这种功能。

你可以读到一篇关于mockito的文章: http://refcardz.dzone.com/refcardz/mockito

使用JMockit框架。这对我很管用。您不必为模拟dbconnection . getconnection()方法编写语句。只要下面的代码就足够了。

下面的@Mock是mockit。模拟方案

Connection jdbcConnection = Mockito.mock(Connection.class);

MockUp<DBConnection> mockUp = new MockUp<DBConnection>() {

            DBConnection singleton = new DBConnection();

            @Mock
            public DBConnection getInstance() { 
                return singleton;
            }

            @Mock
            public Connection getConnection() {
                return jdbcConnection;
            }
         };

当您尝试模拟静态方法时,必须在try块中编写测试。因为重要的是要注意,作用域模拟必须由激活模拟的实体关闭。

      try (MockedStatic<Tester> tester = Mockito.mockStatic(Tester.class)) {
            tester.when(() -> Tester.testStatic("Testing..")).thenReturn(mock(ReturnObject.class));
    //Here you have to write the test cases
      }

在上面的例子中,我们必须模拟测试器类testStatic方法,输入参数为“Testing…”。在这里,该方法将返回一个ReturnObject类类型对象。因此我们写mockito当链像上面。

不要忘记在你的Gradle/maven中添加以下依赖项

    testImplementation 'org.mockito:mockito-inline:4.3.1'

我在《Mockito》中找到了一个解决方法。该特性仅在3.4.0版本中提供

https://asolntsev.github.io/en/2020/07/11/mockito-static-methods/

dependency In your build.gradle replace mockito-core:3.3.3 by mockito-inline:3.4.0: testImplementation('org.mockito:mockito-inline:3.4.0') what are we going to mock class Buddy { static String name() { return "John"; } } Mock the static method @Test void lookMomICanMockStaticMethods() { assertThat(Buddy.name()).isEqualTo("John"); try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) { theMock.when(Buddy::name).thenReturn("Rafael"); assertThat(Buddy.name()).isEqualTo("Rafael"); } assertThat(Buddy.name()).isEqualTo("John"); }

我想这对我们有帮助。

有一个简单的解决方案,使用java FunctionalInterface,然后将该接口添加为您试图进行单元测试的类的依赖项。