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);
}
}
我正在尝试测试旧的纯 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);
}
}