Mockito OracleConnection

Mockito OracleConnection

我正在尝试测试旧的纯 Spring 应用程序。我正在尝试测试 class,它是数据提供者并使用 OracleConnection。我正在为此使用 Mocikto,但任何时候执行与数据库连接相关的代码时都会抛出 NPE。我知道我可以将 parseSQLErrorDB 更改为 public 并做一些 Mockito.when.then 但这不是重点..

我的测试:

public class DataProviderTest {

    @InjectMocks
    DataProvider dataProvider;

    @Mock
    PoolDataSource dataSource;

    @Mock
    OracleCallableStatement oracleCallableStatement;

    @BeforeEach
    public void setUp() throws SQLException {
        MockitoAnnotations.initMocks(this);
        ReflectionTestUtils.setField(dataProvider, "parseSQLErrorFuntion", "String you want to inject");
        Mockito.when(dataSource.getConnection()).thenReturn(Mockito.any(Connection.class));
    }
    
    @Test
    public void parseSQLErrorUnconditionalTest() throws SQLException {
        String messageFromDB = "Error message from database";
        String expected = messageFromDB;
        String actual = dataProvider.parseSQLError("Undefined");
        Mockito.verify(oracleCallableStatement, Mockito.times(1)).execute();
        assertEquals(expected, actual);
    }
}

和数据提供者:

public class DataProvider {
    private static final Logger logger = LoggerFactory.getLogger(DataProvider.class);

    // private OracleDataSource dataSource;
    private PoolDataSource dataSource;
    private boolean isAthenticate;
    private String parseSQLErrorFuntion;
    private boolean isInitialized;
    private boolean ignoreMsgLenLimit;

    public DataProvider() {
        super();
    }

    @PostConstruct
    private void init() {
        OracleConnection conn = null;
        try {
            conn = (OracleConnection) dataSource.getConnection();
           
            loggerInfoAboutDatabase(conn);
            if (!testParseSQLErrorDB(conn)) {
                logger.warn("Brak: parseSQLErrorFuntion");
                parseSQLErrorFuntion = null;
            }
            isInitialized = true;
        } catch (SQLException ex) {
            logger.error("{}", ex.getMessage(), ex);
        } finally {
            closeConnection(null, conn);
        }
    }

    public String parseSQLError(String errorString) {
        if (errorString != null) {
            return parseSQLErrorDB(errorString);
        }
        return errorString;
    }

    private String parseSQLErrorDB(String errorString) {

        OracleCallableStatement cs = null;
        OracleConnection conn = null;
        String callS = "";
        try {
            conn = getConnection();
            ...rest of code
            }
        } catch (SQLException ex) {
            logger.error("Error parseSQLError: {} ; error: {}", callS, ex.getMessage());
        } finally {
            closeConnection(cs, conn);
        }
        return rv;
    }

    

    public void close() {
    }

    public OracleConnection getConnection() throws SQLException {
        ...
    }

    public OracleConnection getConnection(String username, String password) throws SQLException {
        ...
    }

    public static void closeConnection(Connection conn) {
        ...
    }

    public static void closeConnection(CallableStatement cs, Connection conn) {
        ...
    }

    public static void closeConnection(Statement stmt, ResultSet rs, Connection conn) {
        ...
    }


    private void loggerInfoAboutDatabase(Connection connection) throws SQLException {
        DatabaseMetaData dbMetaData = connection.getMetaData();
        logger.info("=============");
        logger.info("Database Product Name is : " + dbMetaData.getDatabaseProductName());
        logger.info("Database Product Version : " + dbMetaData.getDatabaseProductVersion());
        logger.info("JDBC Driver Name          : " + dbMetaData.getDriverName());
        logger.info("JDBC Driver Version is    : " + dbMetaData.getDriverVersion());
        logger.info("JDBC Driver Major Version : " + dbMetaData.getDriverMajorVersion());
        logger.info("JDBC Driver Minor Version : " + dbMetaData.getDriverMinorVersion());
        logger.info("=============");
    }

    ..getters, setters

}

当我在 setUp() 块中执行这一行时

Mockito.when(dataSource.getConnection()).thenReturn(Mockito.any(Connection.class));

我得到了:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at pl.sygnity.common.db.DataProviderTest.setUp(DataProviderTest.java:47)

This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

But when I comment this out, it executes methods and throws NPE on loggerInfoAboutDatabase method..
java.lang.NullPointerException
    at pl.test.common.db.DataProvider.loggerInfoAboutDatabase(DataProvider.java:186)
    at pl.test.common.db.DataProvider.init(DataProvider.java:49)
    at pl.test.common.db.DataProvider.getConnection(DataProvider.java:146)
    at pl.test.common.db.DataProvider.parseSQLErrorDB(DataProvider.java:90)
    at pl.test.common.db.DataProvider.parseSQLError(DataProvider.java:74)
    at pl.test.common.db.DataProviderTest.parseSQLErrorUnconditionalTest(DataProviderTest.java:71)
    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.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at 

有什么想法吗?我能以某种方式伪造这个 PoolDatasource 和所有相关的东西吗?

我终于成功测试了。 基本上我在模拟程序执行期间使用的每个嵌套对象。

public class DataProviderTest {

    @InjectMocks
    DataProvider dataProvider;

    @Mock
    OracleConnection oracleConnection;
    
    @Mock
    DatabaseMetaData databaseMetadata;
    
    @Mock
    PoolDataSource dataSource;

    @Mock
    OracleCallableStatement oracleCallableStatement;

    @BeforeEach
    public void setUp() throws SQLException {
        MockitoAnnotations.initMocks(this);
        ReflectionTestUtils.setField(dataProvider, "parseSQLErrorFuntion", "String you want to inject");
        Mockito.when(dataSource.getConnection()).thenReturn(oracleConnection);
        Mockito.when(oracleConnection.getMetaData()).thenReturn(databaseMetadata);
        Mockito.when(oracleConnection.prepareCall(Mockito.anyString())).thenReturn(oracleCallableStatement);
    }

    
    @Test
    public void parseSQLErrorUnconditionalTest() throws SQLException {
        String messageFromDB = "Error message from database";
        String expected = messageFromDB;
        Mockito.when(oracleCallableStatement.getString(Mockito.anyInt())).thenReturn(messageFromDB);
        String actual = dataProvider.parseSQLError("Undefined");
        Mockito.verify(oracleCallableStatement, Mockito.times(2)).execute();
        assertEquals(expected, actual);
    }
}