Je dois écrire quelques tests unitaires, mais je ne parviens pas à me moquer de ResultSet
et de jdbc Connection
.
J'ai cette méthode:
@Test
public void test3() throws SQLException, IOException {
Connection jdbcConnection = Mockito.mock(Connection.class);
ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");
Mockito.when(jdbcConnection
.createStatement()
.executeQuery("SELECT name FROM tables"))
.thenReturn(resultSet);
//when
List<String> nameOfTablesList = null;
try {
nameOfTablesList = Helper.getTablesName(jdbcConnection);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//then
Assert.assertEquals(nameOfTablesList.size(), 3);
}
Et l'erreur est indiquée sur la ligne executeQuery("SELECT name FROM tables")
et sonne comme ceci:
Java.lang.NullPointerException HelperTest.test3(HelperTest.Java:71)
Des idées qui ne vont pas?
Vous devez créer une expectation on jdbcConnection.createStatement()
.
Par défaut, je crois qu'une null
est renvoyée.
Devrait lire quelque chose comme:
ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");
Statement statement = Mockito.mock(Statement.class);
Mockito.when(statement.executeQuery("SELECT name FROM tables")).thenReturn(resultSet);
Connection jdbcConnection = Mockito.mock(Connection.class);
Mockito.when(jdbcConnection.createStatement()).thenReturn(statement);
Il est assez fastidieux de se moquer de l'API JDBC à ce niveau bas, car vous devriez vraiment vous moquer de l'intégralité de l'API JDBC. Juste quelques exemples:
ResultSet.previous()
?ResultSet.getObject()
plutôt que getString()
?ResultSet
était obtenue par Statement.getResultSet()
?Pour votre code client, peu importe que vous appeliez JDBC d'une manière ou d'une autre, le résultat devrait toujours être le même. Si vous devez obligatoirement simulez la base de données (plutôt que d'utiliser une base de données de test, ou mieux, une approche basée sur testcontainers ), utilisez quelque chose comme jOOQ's MockDataProvider
ou MockFileDatabase
rendrait certainement les choses beaucoup plus simples. Dans ton cas:
MockDataProvider db = new MockFileDatabase(
"SELECT name FROM tables;\n"
+ "> name\n"
+ "> --------\n"
+ "> table_r3\n"
+ "> table_r1\n"
+ "> table_r2\n"
+ "> @rows: 3\n");
//when
List<String> nameOfTablesList = null;
try {
nameOfTablesList = Helper.getTablesName(new MockConnection(db));
} catch (SQLException e) {
e.printStackTrace();
}
//then
Assert.assertEquals(nameOfTablesList.size(), 3);
L'approche ci-dessus fonctionnera indépendamment de la méthode Helper.getTablesName()
avec le JDBC passé Connection
.
Remarque: je travaille pour la société derrière jOOQ, cette réponse est donc biaisée.