单元/集成测试由通用方法组成的dao

时间:2012-02-21 10:29:50

标签: java unit-testing generics

以下是方法的示例:

public <T> T save(final T o){
  return (T) sessionFactory.getCurrentSession().save(o);
}

public <T> T get(final Class<T> type, final Long id){
  return (T) sessionFactory.getCurrentSession().get(type, id);
}

public <T> List<T> getFieldLike(final Class<T> type, final String propertyName,
            final String value, final MatchMode matchMode)  {
    final Session session = sessionFactory.getCurrentSession();
    final Criteria crit = session.createCriteria(type);
    crit.add(Restrictions.like(propertyName, value, matchMode));
    return crit.list();
}

有关单元或集成测试的任何提示吗?通过模拟会话?

3 个答案:

答案 0 :(得分:1)

关于你在单元测试中唯一可以做的就是模拟Session和Criteria并设定期望 - 我在使用JMock的几个案例中做了这个,最后不得不为Restricitons写一个Hamcrest匹配器。除了盲目提高测试覆盖率外,我不相信它有很多价值。

另一方面 - 在这里编写集成测试将是明确的用途,在内存数据库中设置一些数据并声明方法返回正确的对象

答案 1 :(得分:0)

get()的集成测试示例:

// if you can inject the object:
// @Inject 
// public MyTestDAO<MyType> dao;
// 

@Test
public testGet() throws Exception {
    Session session = HibernateUtils.getSessionFactory().getCurrentSession();
    MyTestDAO<MyType> dao = new MyTestDAO<MyType>();
    // if you use DI facility, check against null
    // assertNotNull(dao)
    MyType myType = dao.get(Test.class, 1L);
    assertNotNull(myType);
    assertEqual(myType, equalObj);
    // more asserts? 
}

如果使用spring框架,可以使用spring-test模块使用spring上下文和类运行器来使用DI:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring.xml"})

答案 2 :(得分:0)

根据您的问题,我假设您自己管理会话。我将谈谈单元测试部分。集成测试可以在集成期间在内存数据库中完成。据我所知,H2或Derby是最常用的之一。

你可以通过将模拟会话传递给你的DAO,但如果你的一个同事写了一个单元测试并忘记通过模拟会话会发生什么?你打了数据库吗?如果你不想打数据库,这种方法可能是个问题

更好的方法是使用抽象工厂模式甚至ACQUIRE dao。基本上你的代码目前是这样的:

MyDao.get(someId);

但是,您可以采用以下方式:

如果您首先像这样定义Dao:

public interface IDao <SomeGenerics> {
   public <T> T get(Class<T> type, ID key);
   //more generic methods
}

然后你可以实现Dao的实现,如下所示:

public class MyDao <SomeGenerics> implements IDao<SomeGenerics> {
    public <T> T get(Class<T> type, ID key){
        //some real session stuff
    }
    //...more real session stuff
}

然后在您的单元测试中,您可以定义一个IDao接口的模拟,有点像这样:

public class MyDaoMock <SomeGenerics> implements IDao<SomeGenerics> {
    //this thingy can hold a small array of mock instances
    private ArrayList<T> mockInstances;

    public <T> T get(Class<T> type, ID key){
        //some fake stuff, kinda like this;
        for (T mockInstance : mockInstances) {
               if ( mockInstance.getId().equals(key) ) {//here i assume your T has a method getId, you figure out the kinks
                     return mockInstance;
               }
        }
        //if not found, emulate your persistence's behavior, return null, throw an exception or do whatever
        return null;

    }
    //...more fake stuff
} 

现在你有了一个接口和两个实现,一个用于生产代码,另一个用于单元测试。现在,您所要做的就是实现工厂模式,为您提供正确的生产和测试代码。