2011-01-18 6 views
14

Tomando el ejemplo muy específico de la clase JpaDao definido en este article:¿Qué unidad de prueba escribir para una clase usando genéricos en Java?

public abstract class JpaDao<K, E> implements Dao<K, E> { 
    protected Class<E> entityClass; 

    @PersistenceContext 
    protected EntityManager entityManager; 

    public JpaDao() { 
     ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass(); 
     this.entityClass = (Class<E>) genericSuperclass.getActualTypeArguments()[1]; 
    } 

    public void persist(E entity) { entityManager.persist(entity); } 

    public void remove(E entity) { entityManager.remove(entity); } 

    public E findById(K id) { return entityManager.find(entityClass, id); } 
} 

¿sería mejor para escribir pruebas unitarias para todas las entidades existentes en la aplicación (Order, Customer, libro, etc.), o ¿sería aceptable escribir pruebas unitarias para una sola entidad, como se insinúa en este other question? ¿Hay alguna mejor práctica con respecto a la unidad de prueba de clases de Java utilizando genéricos?

Respuesta

6

Puede escribir una clase de prueba abstracta para entidades que subclasifiquen esto.

Ej:

public abstract class JpaDaoTest<K,E> { 

    abstract protected E getEntity(); 
    abstract protected JpaDao getDAO(); 

    @Test 
    public void testPersistCreatesEntity() 
    { 
     JpaDao dao = getDAO(); 
     dao.persist(getEntity()); 
     // assert 
    } 
} 

El contrato que implementa clases genéricas debe ser capaz de ser probado al igual que genericlly, suponiendo que getEntity() conjuntos y dependencias relacionales correctamente.

Por lo tanto, al subclasificar esta clase de prueba para todos los casos de prueba para sus subclases genéricas, obtiene las pruebas de forma gratuita.

1

Si usa un tipo de entidad diferente hace que se ejecute un código diferente, entonces necesita un caso de prueba por separado.

Probaría tanto como pudiera en un conjunto común de pruebas que solo usan un tipo de entidad. Si la mayoría de su código trata a todas las entidades de la misma manera, entonces no hay necesidad de probarlo más de una vez. Establecí casos de prueba separados para cualquier comportamiento especial que se requiera cuando los DAO de entidades específicas tienen un comportamiento diferente.

1

Desde el FAQ JUnit:

4) ¿En qué condiciones debería probar get() y set) (métodos?

Las pruebas unitarias están destinadas a aliviar el temor de que algo se rompa. Si cree que un método get() o set() podría romperse razonablemente, o de hecho ha contribuido a un defecto, entonces, por supuesto, escriba una prueba.

En resumen, pruebe hasta que esté seguro. Lo que elige evaluar es subjetivo, en función de sus experiencias y nivel de confianza. Recuerde ser práctico y maximizar su inversión de prueba.

También afirma:

"prueba hasta que el miedo se vuelve hacia el aburrimiento."

No creo que su pregunta sea específica de los genéricos ya que la pregunta seguiría siendo la misma incluso si no estuviera usando genéricos. En este caso, elegiría probar un objeto (ya sea real o enlatado para fines de prueba). A medida que descubres problemas, escribe pruebas para abordar esas deficiencias específicas.

0

Si tuviera que probar el comportamiento de la clase con respecto a su semántica de tipo, me gustaría ir a comprobar invariantes de tipo. En otras palabras, intente establecer algunas aserciones que sean verdaderas para todas las combinaciones de tipos, no solo aquellos que espera usar sino cualquier tipo en el universo, incluso aquellos que aún no están inventados.Por ejemplo:

private <K, E> void testTypes(K k, E e) { 
    JpaDao<K, E> dao = new JpaDaoImpl<K, E>(); 

    dao.persist(e); 

    assertEquals(dao.getById(e.getId()).getClass(), e.getClass()); 
} 

@Test 
public void testIntegerAndOrder() { 
    this.<Integer, Order>testTypes(10, new Order()); 
} 

Sede, no importa qué tipo K y se E, se espera que las afirmaciones de mantener (el método testIntegerAndOrder() pone a prueba esta afirmación utilizando un archivo de valores de tipo de hormigón).

Esto, por supuesto, debe usarse junto con las pruebas unitarias, que en realidad están probando el comportamiento de algunos valores particulares de de las variables de tipo. Esta sería la misma prueba unitaria que puedes encontrar en cualquier tutorial de JUnit. Algo en la línea de:

@Test 
public void testDao() throws Exception { 
    JpaDao<Integer, Order> dao = getDao(); 

    Order order = ...; 
    order.setId(10); 

    dao.persist(order); 

    assertEquals(order, dao.findById(10)); 
} 

Vea cómo la semántica de las afirmaciones difieren aquí: esta prueba prueba de la afirmación de que mantiene su objeto almacenado ID mediante un valor concreto de la variable de identificación, no la variable tipo que la prueba antes.

1

Al igual que BalusC, recomiendo probar implementaciones concretas. La razón de esto es que se ajusta al principio "No va a necesitarlo". Agregue solo suficientes pruebas para que pase el caso de uso que está tratando de implementar. Luego, a medida que agrega más casos de uso, agregue más pruebas unitarias.

0

Pruebe la clase concreta para evitar el problema de anularla más adelante.

Es hermoso hacer pruebas genéricas pero no es seguro.

Puede copiar la mayor parte de la Prueba de unidad durante el desarrollo, y luego puede personalizar las pruebas.

Cuestiones relacionadas