2011-01-18 56 views
14

服用JpaDao类的在这个article规定的非常具体的例子:在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); } 
} 

会是最好写在应用程序中所有的现有实体(OrderCustomer,图书等)的单元测试,还是仅仅为一个实体编写单元测试是可以接受的,正如other question所暗示的那样?有没有关于使用泛型的单元测试Java类的最佳做法?

回答

6

你可以编写一个抽象的测试类,用于实现它的子类。

如:

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

您泛型类实现合同应是能够如同genericlly测试,正确假设getEntity()套和关系的依赖关系。

因此,通过为所有通用子类的测试用例子类化这个测试类,您可以免费获得测试。

1

如果使用不同的实体类型会导致不同的代码执行,那么您需要单独的测试用例。

我会尽可能多地测试一个只使用一种实体类型的常见测试集。如果大多数代码将所有实体视为相同,则不需要多次测试它。我将针对特定实体DAO具有不同行为的特殊行为设置单独的测试用例。

1

从JUnit的常见问题解答:

4)在什么情况下应该怎么测试get()和set()方法?

单元测试旨在缓解某些可能会破坏的恐惧。如果您认为get()或set()方法可能合理地中断,或者实际上导致了缺陷,那么通过一切手段编写测试。

总之,测试,直到你有信心。根据你的经验和信心水平,你选择测试的是主观的。记住要切实可行并最大化您的测试投资。

报告还指出:

“测试,直到恐惧变成无聊。”

我不认为你的问题是具体到泛型,因为即使你不使用泛型,问题仍然是相同的。在这种情况下,我会选择测试一个对象(无论是真实还是罐装用于测试目的)。当你发现问题时,编写测试来解决这些特定的缺陷。

0

如果我需要测试类的行为与它的类型语义,我会去检查类型不变量。换句话说,试着建立一些对于全部类型的组合都是正确的断言,不仅是那些你期望使用的,而是宇宙中的任何类型,包括那些还没有发明的类型。例如:

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

见,无论是,断言预计将持有什么类型的KE(该testIntegerAndOrder()方法测试使用的具体类型值这一说法)。

这当然应该与单元测试一起使用,它们实际上测试了类型变量的某些特定值的行为。这与您可以在任何JUnit教程中找到的单元测试非常相似。东西的静脉:

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

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

    dao.persist(order); 

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

参见断言的语义如何这里不同:该试验测试存储对象保存使用可变ID的具体值,而不是类型变量如之前测试其ID的断言。

1

和BalusC一样,我推荐测试具体的实现。这是因为它符合“你不需要它”的原则。添加足够的测试,以便您尝试实施的用例通过。然后,当你添加更多的用例时,添加更多的单元测试。

0

测试具体类避免稍后覆盖它的问题。

进行通用测试很不错,但它不安全。

您可以在开发过程中复制大部分单元测试,稍后您可以自定义测试。