2008-11-05 21 views
41

Me gustaría escribir algunas pruebas unitarias para algún código que se conecta a una base de datos, ejecuta una o más consultas y luego procesa los resultados. (sin usar una base de datos)¿Cómo puedo probar el código jdbc en java?

Otro desarrollador aquí escribió nuestro propio origen de datos, conexión, Statement, PreparedStatement, y la aplicación conjunto de resultados que devolverá los objetos correspondientes en base a un archivo de configuración XML. (podríamos usar el origen de datos falso y simplemente ejecutar pruebas contra los conjuntos de resultados que devuelve).

¿Estamos reinventando la rueda aquí? ¿Ya existe algo como esto para las pruebas unitarias? ¿Hay otras/mejores formas de probar el código jdbc?

Respuesta

22

Puede usar DBUnit junto con HSQLDB que puede leer sus datos iniciales de archivos CSV, por ejemplo.

+0

¿Puede proporcionar algún ejemplo? Estoy buscando ejemplos pero no puedo encontrar ninguno que sea fácil de seguir. Estoy usando maven. –

1

Hay DBUnit. No le permitirá probar su código jdbc sin una base de datos, pero parece que podría introducir un conjunto diferente de compras emulando una base de datos.

4

Es por eso que tiene derby (ahora llamado JavaDB) o sqlite - son bases de datos pequeñas y simples que puede crear, cargar, probar y destruir de forma relativamente rápida y sencilla.

+6

Pero cualquier código que dependa del SQL específico del proveedor que no sea compatible con el archivo db liviano no será comprobable. – Asaph

+1

@Asaph: "SQL específico del vendedor" suele ser un error. Sin embargo, cuando vas a probar el SQL específico del proveedor, no estás haciendo pruebas unitarias, así que no es realmente un problema de prueba unitaria, ¿o sí? –

+1

Es más una prueba de integración que una prueba de unidad en ese punto. Pero la conexión a MySQL en una prueba JUnit no es fundamentalmente diferente de la conexión a sqlite de una prueba JUnit. Veo ambos escenarios como pruebas de integración. Lo que realmente lo convertiría en una "unidad" de prueba sería tener burlas o falsificaciones en todas las costuras de la base de datos, es decir.ningún servidor de base de datos (liviano o pesado) en absoluto. Habiendo dicho eso, no soy fanático de adherirme a este principio _todo el tiempo. Siempre y cuando las pruebas se ejecuten rápidamente y no requieran mucha configuración manual, estoy de acuerdo conmigo. – Asaph

6

Utilice cualquiera de los marcos de Mock para tal tarea. (jMock, etc.)

Algunos examples

2

diría que HSQL es el camino a seguir durante las pruebas unitarias. El objetivo de tu prueba es probar tu código jdbc y asegurarte de que funciona. Agregar clases personalizadas o burlarse de las llamadas jdbc puede ocultar fácilmente los errores.

Principalmente uso mysql y cuando las pruebas se ejecutan, la clase del controlador y la URL se cambian a org.hsqldb.jdbcDriver y jdbc: hsqldb: mem: test.

1

Si bien la forma de simular jdbc en su aplicación depende, por supuesto, de cómo haya implementado sus transacciones jdbc reales.

Si está utilizando jdbc como está, supongo que se ha escrito una clase de utilidad para hacer algunas tareas en la línea DBUtils.getMetadataFor(String tablename). Lo que esto significa es que tendrías que crear un simulacro de esa clase y eso podría ser todo lo que necesitas. Esta sería una solución bastante fácil para usted, ya que aparentemente ya tiene disponibles una serie de objetos falsos relacionados con jdbc. Tenga en cuenta que supongo que su código jdbc no se ha explotado en toda la aplicación, si es así, ¡refactorícese!

Sin embargo, si está utilizando cualquier marco para el manejo de bases de datos (como las clases de plantilla JDBC de Spring Framework) puede y debe simular la clase de interfaz usando EasyMock u otro equivalente. De esta forma, puede tener todo el poder del mundo requerido para burlarse fácilmente de la conexión.

Y por último si nada funciona, puede hacer lo que otros ya han dicho y usar DBUnit y/o derby.

30

tiene varias opciones:

  • Mock la base de datos con una biblioteca Mock, por ejemplo, JMock. El gran inconveniente de esto es que sus consultas y los datos probablemente no serán probados en absoluto.
  • Utilice una base de datos liviana para las pruebas, como HSQLDB. Si sus consultas son simples, esta es probablemente la forma más fácil de hacerlo.
  • Dedique una base de datos para las pruebas. DBUnit es una buena opción, o si está usando Maven, también puede usar el sql-maven-plugin para configurar y destruir la base de datos correctamente (tenga cuidado con las dependencias entre las pruebas). Recomiendo esta opción, ya que le dará la mayor seguridad de que las consultas funcionan correctamente con su proveedor de db.

A veces es necesario y útil hacer estas pruebas configurables para que estas pruebas solo se ejecuten si la base de datos está disponible. Esto se puede hacer con, por ejemplo, construir propiedades

+0

Gracias me gusta la idea de usar maven para configurar/desmantelar la base de datos. Estamos utilizando maven ahora para compilaciones, así que esto sería bastante fácil para nosotros. – ScArcher2

+0

El enlace DBUnit (http://www.dbunit.org/) lleva a un sitio web chino que puede no tener nada que ver con DBUnit. – user3885927

+0

@ user3885927 He reparado el enlace. La próxima vez que vea algo así, siéntase libre de enviar una edición para arreglar el enlace roto. – Laf

2

Prefiero usar EasyMock para probar un código no tan fácil de probar.

8

me gusta usar una combinación de:

se puede llegar muy lejos con sólo DBUnit y HSQLDB. Unitils proporciona la última milla de código para administrar y restablecer el estado de la base de datos. También proporciona una forma agradable de gestionar los cambios en el esquema de la base de datos y facilita el uso de RBDMS específicos (Oracle, DB2, SQL Server, etc.). Finalmente, Unitils proporciona algunas envolturas agradables alrededor de DBUnit que moderniza la API y hace que DBUnit sea mucho más agradable para trabajar.

Si aún no ha revisado Unitils, definitivamente debería. Unitils a menudo es pasado por alto y subestimado.

+0

Esta es la pila que suelo usar también. DBUnit/H2/Unitils – cwash

0

controlador Acólito puede ser utilizado para burlarse de una conexión JDBC, su gestión durante las pruebas y devolver datos mientras que el conjunto de resultados (con su typesafe lista fila API): https://github.com/cchantep/acolyte

1

Si usted quiere hacer las pruebas de unidad, no una pruebas de integración, que puede utilizar un enfoque muy básica y sencilla, utilizando sólo Mockito, así:

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

de lo que puede probar varios escenarios, como en cualquier otra prueba Mockito por ejemplo,

@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)); 
} 
Cuestiones relacionadas