web-dev-qa-db-fra.com

Comment tester le code jdbc en java?

J'aimerais écrire des tests unitaires pour du code qui se connecte à une base de données, exécute une ou plusieurs requêtes, puis traite les résultats . (Sans utiliser réellement de base de données)

Un autre développeur a écrit ici notre propre implémentation DataSource, Connection, Statement, PreparedStatement et ResultSet qui renverra les objets correspondants en fonction d'un fichier de configuration xml. (nous pourrions utiliser la source de données fictive et simplement exécuter des tests sur les ensembles de résultats renvoyés).

Sommes-nous réinventer la roue ici? Existe-t-il déjà quelque chose comme ceci pour les tests unitaires? Existe-t-il d'autres/meilleurs moyens de tester le code jdbc?

43
ScArcher2

Vous pouvez utiliser DBUnit avec un HSQLDB qui peut lire ses données initiales à partir de fichiers CSV, par exemple.

23
WMR

Vous avez plusieurs options:

  • Mock la base de données avec une bibliothèque Mock, par ex. JMock . L'énorme inconvénient de ceci est que vos requêtes et les données ne seront probablement pas testées du tout.
  • Utilisez une base de données légère pour les tests, telle que HSQLDB . Si vos requêtes sont simples, c'est probablement la façon la plus simple de procéder. 
  • Dédiez une base de données pour les tests. DBUnit est une bonne option. Si vous utilisez Maven, vous pouvez également utiliser sql-maven-plugin pour configurer et détruire correctement la base de données (faites attention aux dépendances entre les tests). Je recommande cette option car elle vous donnera la plus grande confiance dans le fait que les requêtes fonctionnent correctement avec votre fournisseur de base de données. 

Il est parfois nécessaire et utile de rendre ces tests configurables afin que ces tests ne soient exécutés que si la base de données est disponible. Cela peut être fait avec par exemple construire des propriétés.

30
Tatu Lahtela

J'aime utiliser une combinaison de:

Vous pouvez aller assez loin avec seulement DBUnit et HSQLDB. Unitils fournit le dernier kilomètre de code pour gérer et réinitialiser l'état de la base de données. Il fournit également un moyen pratique de gérer les modifications de schéma de base de données et facilite l’utilisation de RBDMS spécifiques (Oracle, DB2, SQL Server, etc.). Enfin, Unitils fournit quelques wrappers Nice autour de DBUnit, qui modernisent l’API et rendent DBUnit bien plus agréable à utiliser.

Si vous n'avez pas encore vérifié Unitils, vous devriez le faire. Unitils est souvent négligé et sous-estimé.

8
Jim Hurne

Utilisez n'importe lequel des frameworks Mock pour une telle tâche. ( jMock , etc .)

Quelques exemples

6
Sunny Milenov

C'est pourquoi vous avez derby (maintenant appelé JavaDB) ou sqlite - il s'agit de petites bases de données simples que vous pouvez créer, charger, tester et détruire relativement rapidement et simplement.

4
S.Lott

Je préfère utiliser EasyMock pour tester un code pas-si-facile-à-tester.

2
folone

Je dirais que HSQL est la voie à suivre lors de vos tests unitaires. Le but de votre test est de tester votre code jdbc et de vous assurer qu'il fonctionne. Ajouter des classes personnalisées ou se moquer des appels jdbc peut facilement cacher des bugs.

J'utilise principalement mysql et lorsque les tests exécutent la classe de pilote et que l'URL est modifiée en org.hsqldb.jdbcDriver et jdbc: hsqldb: mem: test.

2
user30684

Si vous souhaitez effectuer des tests unitaires et non des tests d'intégration, vous pouvez utiliser une approche très basique et simple, utilisant uniquement Mockito, comme ceci:

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);        
    }
}

Ensuite, vous pouvez tester différents scénarios, comme dans tout autre test Mockito, par exemple.

@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

Bien que la manière de se moquer de jdbc dans votre application dépende, bien sûr, de la manière dont vous avez implémenté vos transactions jdbc réelles.

Si vous utilisez jdbc en l'état, je suppose que vous avez écrit vous-même une classe d'utilitaires pour effectuer certaines tâches dans la ligne de DBUtils.getMetadataFor(String tablename). Cela signifie que vous devez créer une maquette de cette classe et que cela pourrait être tout ce dont vous avez besoin. Ce serait une solution assez facile pour vous puisque vous avez apparemment déjà une série d'objets fictifs liés à jdbc. Notez que je suppose que votre code jdbc n’est pas explosé tout autour de l’application - si c’est le cas, refactor !!!

Si vous utilisez toutefois un cadre pour la gestion de base de données (comme les classes de modèle JDBC de Spring Framework), vous pouvez et devriez vous moquer de la classe d'interface en utilisant EasyMock ou un autre équivalent. De cette façon, vous pouvez disposer de toute la puissance nécessaire pour vous permettre de vous moquer de la connexion.

Enfin, si rien ne fonctionne, vous pouvez faire ce que d’autres ont déjà dit et utiliser DBUnit et/ou derby.

1
P Arrayah

Il y a DBUnit . Cela ne vous permettra pas de tester votre code jdbc sans base de données, mais il semble que vous puissiez introduire un ensemble différent d’achats en émulant une base de données.

1
Steve K

Le pilote Acolyte peut être utilisé pour créer une connexion JDBC, la gérer pendant les tests et renvoyer les données sous forme de jeu de résultats (avec son API de liste de lignes dactylographiée): https://github.com/cchantep/acolyte

Note: Je suis l'auteur de Acolyte.

0
cchantep

Jetez un coup d'œil à JDBDT: http://jdbdt.org

Vous pouvez l'utiliser pour la configuration de la base de données et des assertions, au lieu de DBUnit.

Note: Je suis l'auteur de JDBDT.

0
edrdo

Nous utilisons Mockrunner. http://mockrunner.sourceforge.net/ Il possède des connexions fictives et des sources de données intégrées, il n'est donc pas nécessaire de les implémenter vous-même.

0
grbonk