2011-01-18 14 views
14

Prendendo l'esempio molto specifico della classe JpaDao definito in questo article:Quale unit test per scrivere per una classe usando i generici in 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); } 
} 

sarebbe meglio scrivere test di unità per tutte le entità esistenti nell'applicazione (Order, Customer, libro, ecc), o sarebbe accettabile scrivere test unitari per una sola entità, come suggerito da questo other question? Ci sono buone pratiche per quanto riguarda le unità di test delle classi Java che utilizzano i generici?

risposta

6

È possibile scrivere una classe di test astratta per entità che la sottoclasse.

Esempio:

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

Il contratto si classi generiche implementare dovrebbe essere in grado di essere testato proprio come genericlly, assumendo che getEntity() set up e le dipendenze relazionali in modo corretto.

Pertanto, sottoclassi questa classe di test per tutti i casi di test per le sottoclassi generiche, i test sono gratuiti.

1

Se l'utilizzo di un tipo di entità differente causa l'esecuzione di codice diverso, è necessario un caso di test separato.

Provavo il più possibile in un set comune di test che utilizza solo un tipo di entità. Se la maggior parte del tuo codice tratta tutte le entità allo stesso modo, non c'è bisogno di testarlo più di una volta. Avrei impostato casi di test separati per qualsiasi comportamento speciale richiesto quando specifici DAO di entità hanno un comportamento diverso.

1

Dal JUnit FAQ:

4) A quali condizioni dovrei provare get() e impostare metodi()?

I test unitari hanno lo scopo di alleviare la paura che qualcosa possa rompersi. Se pensate che un metodo get() o set() possa ragionevolmente rompersi, o abbia di fatto contribuito a un difetto, allora scrivete con tutti i mezzi un test.

In breve, prova finché non sei sicuro. Quello che scegli di testare è soggettivo, in base alle tue esperienze e al tuo livello di fiducia. Ricorda di essere pratico e massimizza il tuo investimento di test.

Essa afferma inoltre:

"Test fino a quando la paura si trasforma alla noia."

Non penso che la tua domanda sia specifica dei generici poiché la domanda sarebbe ancora la stessa anche se non si usassero i farmaci generici. In questo caso, sceglierei di testare un oggetto (reale o in scatola a scopo di test). Man mano che si scoprono problemi, scrivere test per risolvere quelle carenze specifiche.

0

Se avessi bisogno di testare il comportamento della classe per quanto riguarda la semantica del suo tipo, vorrei verificare gli invarianti di tipo. In altre parole, prova a stabilire alcune asserzioni che sono vere per la combinazione di tipi , non solo quelli che prevedi di utilizzare ma qualsiasi tipo nell'universo, inclusi quelli che non sono ancora stati inventati.Per esempio:

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, non importa quale tipo K e E sono, le affermazioni sono tenuti a tenere (il metodo testIntegerAndOrder() mette alla prova questa affermazione utilizzando un tipo concreto valori).

Questo, ovviamente, dovrebbe essere utilizzato in combinazione con i test di unità, che in realtà stanno testando il comportamento per alcuni valori di tipo variabili di tipo. Questo sarebbe molto lo stesso test unitario che potresti trovare in qualsiasi tutorial di JUnit. Qualcosa in vena di:

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

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

    dao.persist(order); 

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

Vedere come semantica di asserzioni differiscono qui: questo test di prova l'affermazione che oggetto memorizzato tiene il suo ID utilizzando un valore concreto di ID variabile, non il tipo di variabile come il test prima.

1

Come BalusC, suggerisco di testare le implementazioni concrete. La ragione di ciò è che è conforme al principio "Non hai bisogno di averlo". Aggiungi solo un numero sufficiente di test in modo che il caso d'uso che stai cercando di implementare passa. Quindi, quando aggiungi più casi d'uso, aggiungi più test unitari.

0

Verificare la classe concreta evitare il problema di annullarla in seguito.

È bello fare test generici ma non è sicuro.

È possibile copiarePaste gran parte del Test unità durante lo sviluppo e successivamente è possibile personalizzare i test.

Problemi correlati