Ich möchte einige Komponententests für Code schreiben, der eine Verbindung zu einer Datenbank herstellt, eine oder mehrere Abfragen ausführt und dann die Ergebnisse verarbeitet. (Ohne tatsächlich eine Datenbank zu verwenden).
Ein anderer Entwickler hat hier eine eigene Implementierung von DataSource, Connection, Statement, PreparedStatement und ResultSet geschrieben, die die entsprechenden Objekte basierend auf einer XML-Konfigurationsdatei zurückgibt. (Wir könnten die falsche Datenquelle verwenden und einfach Tests mit den zurückgegebenen Ergebnismengen ausführen).
Werden wir das Rad hier neu erfinden? Gibt es so etwas bereits für Unit-Tests? Gibt es andere/bessere Möglichkeiten, jdbc-Code zu testen?
Sie haben mehrere Möglichkeiten:
Manchmal ist es notwendig und sinnvoll, diese Tests konfigurierbar zu machen, sodass diese Tests nur ausgeführt werden, wenn die Datenbank verfügbar ist. Dies kann mit z. Eigenschaften erstellen.
Ich benutze gerne eine Kombination aus:
Mit DBUnit und HSQLDB können Sie ziemlich weit kommen. Unitils bietet die letzte Meile des Codes zum Verwalten und Zurücksetzen des Datenbankstatus. Es bietet auch eine nette Möglichkeit zum Verwalten von Änderungen an Datenbankschemas und vereinfacht die Verwendung bestimmter RBDMS (Oracle, DB2, SQL Server usw.). Schließlich stellt Unitils einige schöne Wrapper für DBUnit bereit, die die API modernisieren und DBUnit viel angenehmer machen.
Wenn Sie Unitils noch nicht ausgecheckt haben, sollten Sie dies definitiv tun. Unitils wird oft übersehen und unterschätzt.
Ich bevorzuge die Verwendung von EasyMock zum Testen eines nicht so einfach zu testenden Codes.
Ich würde sagen, dass HSQL der Weg ist, um Ihre Unit-Tests durchzuführen. Der Zweck Ihres Tests ist es, Ihren jdbc-Code zu testen und sicherzustellen, dass er funktioniert. Durch das Hinzufügen von benutzerdefinierten Klassen oder das Verspotten der Jdbc-Aufrufe können Fehler leicht ausgeblendet werden.
Ich verwende meistens mysql und wenn die Tests ausgeführt werden, werden die Treiberklasse und die URL in org.hsqldb.jdbcDriver und jdbc: hsqldb: mem: test geändert.
Wenn Sie Unit-Tests und keine Integrationstests durchführen möchten, können Sie einen sehr einfachen und einfachen Ansatz verwenden, der nur Mockito verwendet:
public class JDBCLowLevelTest {
private TestedClass tested;
private Connection connection;
private static Driver driver;
@BeforeClass
public static void setUpClass() throws Exception {
// (Optional) Print DriverManager logs to system out
DriverManager.setLogWriter(new PrintWriter((System.out)));
// (Optional) Sometimes you need to get rid of a driver (e.g JDBC-ODBC Bridge)
Driver configuredDriver = DriverManager.getDriver("jdbc:odbc:url");
System.out.println("De-registering the configured driver: " + configuredDriver);
DriverManager.deregisterDriver(configuredDriver);
// Register the mocked driver
driver = mock(Driver.class);
System.out.println("Registering the mock driver: " + driver);
DriverManager.registerDriver(driver);
}
@AfterClass
public static void tearDown() throws Exception {
// Let's cleanup the global state
System.out.println("De-registering the mock driver: " + driver);
DriverManager.deregisterDriver(driver);
}
@Before
public void setUp() throws Exception {
// given
tested = new TestedClass();
connection = mock(Connection.class);
given(driver.acceptsURL(anyString())).willReturn(true);
given(driver.connect(anyString(), Matchers.<Properties>any()))
.willReturn(connection);
given(connection.prepareCall(anyString())).willReturn(statement);
}
}
Dann können Sie verschiedene Szenarien testen, wie in jedem anderen Mockito-Test, z.
@Test
public void shouldHandleDoubleException() throws Exception {
// given
SomeData someData = new SomeData();
given(connection.prepareCall(anyString()))
.willThrow(new SQLException("Prepare call"));
willThrow(new SQLException("Close exception")).given(connection).close();
// when
SomeResponse response = testClass.someMethod(someData);
// then
assertThat(response, is(SOME_ERROR));
}
Die Art und Weise, wie man jdbc in Ihrer Anwendung simuliert, hängt natürlich davon ab, wie Sie Ihre tatsächlichen jdbc-Transaktionen implementiert haben.
Wenn Sie jdbc verwenden, würde ich davon ausgehen, dass Sie sich selbst eine Dienstprogrammklasse geschrieben haben, um einige Aufgaben in der Zeile von DBUtils.getMetadataFor(String tablename)
auszuführen. Das würde bedeuten, dass Sie ein Modell dieser Klasse erstellen müssten, und das könnte alles sein, was Sie brauchen. Dies wäre eine relativ einfache Lösung für Sie, da Sie offenbar bereits eine Reihe von Jdbc-bezogenen Mock-Objekten zur Verfügung haben. Beachten Sie, dass ich davon ausgehe, dass Ihr JDBC-Code nicht überall in der Anwendung explodiert ist.
Wenn Sie jedoch ein Framework für die Datenbankverarbeitung verwenden (wie die JDBC-Vorlagenklassen von Spring Framework), können und sollten Sie die Schnittstellenklasse mit EasyMock oder einem anderen Äquivalent simulieren. Auf diese Weise können Sie die gesamte Macht der Welt haben, die für das einfache Verspotten der Verbindung erforderlich ist.
Und wenn nichts anderes funktioniert, können Sie tun, was andere bereits gesagt haben, und DBUnit und/oder Derby verwenden.
Es gibt DBUnit . Sie können Ihren jdbc-Code nicht ohne eine Datenbank testen. Es scheint jedoch, als könnten Sie durch Emulation einer Datenbank einen anderen Kaufsatz einführen.
Der Acolyte-Treiber kann verwendet werden, um eine JDBC-Verbindung zu simulieren, sie während Tests zu verwalten und Daten als Ergebnismenge (mit ihrer typsicheren Zeilenlisten-API) zurückzugeben: https://github.com/cchantep/acolyte
Hinweis: Ich bin der Autor von Acolyte.
Schauen Sie sich JDBDT an: http://jdbdt.org
Sie können es als Alternative zu DBUnit für das Datenbank-Setup und für Assertions verwenden.
Hinweis: Ich bin der Autor von JDBDT.
Wir verwenden Mockrunner. http://mockrunner.sourceforge.net/ Es sind Mock-Verbindungen und Datenquellen eingebaut, sodass Sie sie nicht selbst implementieren müssen.