测试通用 DAO 的最佳实践

Best practise testing generic DAO

我有一个抽象的 GenericDAO,其中包含适用于所有实体的通用方法。我正在使用 Spring 和 Hibernate 项目。 GenericDAO 的源代码是:

public abstract class GenericDAOImpl <T, PK extends Serializable> implements GenericDAO<T, PK> {

private SessionFactory sessionFactory;

/** Domain class the DAO instance will be responsible for */
private Class<T> type;

@SuppressWarnings("unchecked")
public GenericDAOImpl() {
    Type t = getClass().getGenericSuperclass();
    ParameterizedType pt = (ParameterizedType) t;
    type = (Class<T>) pt.getActualTypeArguments()[0];
}

@SuppressWarnings("unchecked")
public PK create(T o) {
    return (PK) getSession().save(o);
}

public T read(PK id) {
    return (T) getSession().get(type, id);
}

public void update(T o) {
    getSession().update(o);
}

public void delete(T o) {
    getSession().delete(o);
}

我创建了一个 genericDAOTest class 来测试这个通用方法,并且不必在不同实体的每个测试用例中重复它们,但我找不到这样做的方法。有什么方法可以避免在每个 class 中测试这个泛型方法?谢谢!

我正在使用 DBUnit 测试 DAO classes。对于 testShouldSaveCorrectEntity 我无法创建 "Generic Entity" 因为每个实体都没有我必须设置的空字段。所以,我认为这是不可能的。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/com//spring/dao-app-ctx-test.xml")
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
    TransactionDbUnitTestExecutionListener.class})
@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public abstract class GenericDAOTest<T, PK extends Serializable> {
protected GenericDAO<T, PK> genericDAO;

public abstract GenericDAO<T, PK> makeGenericDAO();

@Test
@SuppressWarnings("unchecked")
public void testShouldGetEntityWithPK1() {
    /* If in the future exists a class with a PK different than Long, 
    create a conditional depending on class type */
    Long pk = 1l;

    T entity = genericDAO.read((PK) pk);
    assertNotNull(entity);
}

@Test
public void testShouldSaveCorrectEntity() {

}

}

如果您的 GenericDAOImpl 是 Hibernate Session 的简单包装器,并且您不得不为此实现创建测试,那么我建议创建一个非常基本的实体和相应的实现您的 GenericDAOImpl 用于所述实体。

例如:

@Entity
public class BasicTestEntity {
  @Id @GeneratedValue private Integer id;
  private String name;
}

public class BasicTestEntityDao 
    extends GenericDaoImpl<BasicTestEntity, Integer> {
}

如果您发现在某些情况下需要对此层进行更明确的测试,只需添加它们并使用 mock/simple 类 进行测试。

这里的任何内容都不需要与您在更高级别的代码中使用的实际真实实体相关联。这种类型的测试将通过针对那些特定模块和层的集成和单元测试浮出水面。