英文:
Mockito OracleConnection
问题
以下是翻译的内容:
我正在尝试测试一个旧的纯Spring应用程序。我试图测试一个作为数据提供程序并使用OracleConnection的类。我在使用Mocikto进行测试,但每当执行与数据库连接相关的代码时,它就会抛出NPE(NullPointerException)。我知道我可以将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", "要注入的字符串");
Mockito.when(dataSource.getConnection()).thenReturn(Mockito.any(Connection.class));
}
@Test
public void parseSQLErrorUnconditionalTest() throws SQLException {
String messageFromDB = "来自数据库的错误消息";
String expected = messageFromDB;
String actual = dataProvider.parseSQLError("未定义");
Mockito.verify(oracleCallableStatement, Mockito.times(1)).execute();
assertEquals(expected, actual);
}
}
DataProvider类:
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("缺少: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();
// ...剩余的代码
} catch (SQLException ex) {
logger.error("Error parseSQLError: {} ; error: {}", callS, ex.getMessage());
} finally {
closeConnection(cs, conn);
}
return rv;
}
// ...其他方法
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("=============");
}
// ...getter和setter方法
}
当我在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和所有相关的内容吗?
英文:
I am trying to test old pure Spring app. I am trying to test class which is data provider and uses OracleConnection. I am using Mocikto for this but any time when database conection related code is executed it throws NPE. I know that i could change parseSQLErrorDB to public and do kind of Mockito.when.then but that is not the point..
My test:
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);
}
}
And DataProvider:
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
}
When i execute this line in setUp() block
Mockito.when(dataSource.getConnection()).thenReturn(Mockito.any(Connection.class));
I got:
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
Any ideas here? Can I fake somehow this PoolDatasource and all related stuff?
答案1
得分: 1
我终于成功地进行了测试。
基本上,我正在模拟程序执行期间使用的每个嵌套对象。
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", "您想要注入的字符串");
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 = "来自数据库的错误消息";
String expected = messageFromDB;
Mockito.when(oracleCallableStatement.getString(Mockito.anyInt())).thenReturn(messageFromDB);
String actual = dataProvider.parseSQLError("未定义");
Mockito.verify(oracleCallableStatement, Mockito.times(2)).execute();
assertEquals(expected, actual);
}
}
英文:
I finally managed to test it.
Basically I am mocking every nested objects that are used during program execution.
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);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论