web-dev-qa-db-de.com

Wie kann ich JDBC-Code in Java testen?

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?

43
ScArcher2

Sie könnten DBUnit zusammen mit einem HSQLDB verwenden, das beispielsweise die ursprünglichen Daten aus CSV-Dateien lesen kann.

23
WMR

Sie haben mehrere Möglichkeiten:

  • Verspotten Sie die Datenbank mit einer Mock-Bibliothek, z. JMock . Der große Nachteil dabei ist, dass Ihre Abfragen und Daten höchstwahrscheinlich überhaupt nicht getestet werden.
  • Verwenden Sie eine leichte Datenbank für die Tests, z. B. HSQLDB . Wenn Ihre Fragen einfach sind, ist dies wahrscheinlich der einfachste Weg. 
  • Bestimmen Sie eine Datenbank für die Tests. DBUnit ist eine gute Option, oder wenn Sie Maven verwenden, können Sie auch das sql-maven-plugin verwenden, um die Datenbank richtig einzurichten und abzubauen (achten Sie auf Abhängigkeiten zwischen Tests). Ich empfehle diese Option, da Sie dadurch das größte Vertrauen haben, dass die Abfragen ordnungsgemäß mit Ihrem Datenbankanbieter funktionieren. 

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.

30
Tatu Lahtela

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.

8
Jim Hurne

Verwenden Sie für eine solche Aufgabe eines der Mock-Frameworks. ( jMock , etc .)

Einige Beispiele

6
Sunny Milenov

Aus diesem Grund haben Sie derby (jetzt JavaDB genannt) oder sqlite - kleine, einfache Datenbanken, die Sie relativ schnell und einfach erstellen, laden, testen und zerstören können.

4
S.Lott

Ich bevorzuge die Verwendung von EasyMock zum Testen eines nicht so einfach zu testenden Codes.

2
folone

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.

2
user30684

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));
}
1
Paweł Prażak

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.

1
P Arrayah

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.

1
Steve K

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.

0
cchantep

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.

0
edrdo

Wir verwenden Mockrunner. http://mockrunner.sourceforge.net/ Es sind Mock-Verbindungen und Datenquellen eingebaut, sodass Sie sie nicht selbst implementieren müssen.

0
grbonk