【问题标题】:Testing Hibernate DAO methods with mockito使用 mockito 测试 Hibernate DAO 方法
【发布时间】:2019-03-07 17:31:46
【问题描述】:

我访问了很多博客和网站,以了解如何使用 Mockito 在 Hibernate 中测试我的 DAO 方法,但我没有找到任何可以帮助我编写代码的具体示例。我发现我必须使用集成测试而不是 JUnit 测试,但我真的不知道如何用我的代码来做到这一点。

问题:如何尽可能好地测试我的 DAO 方法?

我的密码:

我的测试只使用了 mockito 部分:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class UserDAOTest
{

@Mock
private UserDAO userDAO;

@Before
public void setUp()
{
    MockitoAnnotations.initMocks(this);
}

@Test
public void testAddUser_AddsNewUser()
{

}

@Test
public void testDeleteUser_DeletesUser()
{

}


@Test
public void testGetUser_FetchUser()
{

}

@Test
public void testGetUsers_FetchesAllUsers()
{

}
}

我的用户DAO:

import Hibernate.HibernateUtil;
import Hibernate.Models.User;
import org.hibernate.HibernateException;
import org.springframework.stereotype.Repository;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.List;

//@Transactional
@Repository
public class UserDAO extends GeneralDAO
{

public void addUser(User user)
{
    add(user);
}


/**
 * Deletes a user from the database based on the userID
 * @param userID
 */

public void deleteUser(int userID)
{
    User user = new User();
    delete(userID, user);
}


public User getUser(int userID) throws Exception
{
    Transaction transaction = null;
    User user = null;
    try (Session session = HibernateUtil.getSessionFactory().openSession()) 
{
        // start a transaction
        transaction = session.beginTransaction();

        // Gets the user object
        user = session.get(User.class, userID);

        // commit transaction
        transaction.commit();

        //closing session
        session.close();

        return user;

    } catch (Exception e) {
        if (transaction != null) {
            transaction.rollback();
        }
        e.printStackTrace();
        return user;
    }
}


public List<User> getUsers() throws HibernateException, Exception
{
    try(Session session = HibernateUtil.getSessionFactory().openSession()){
        return session.createQuery("FROM User", User.class).getResultList();
    }

}
}

我的 GeneralDAO:

import Hibernate.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.stereotype.Repository;

//@Transactional
@Repository
public class GeneralDAO
{
public void add(Object obj)
{
    Transaction transaction = null;
    try (Session session = HibernateUtil.getSessionFactory().openSession())
    {
        // start a transaction
        transaction = session.beginTransaction();

        // add the user object
        session.save(obj);

        // commit transaction
        transaction.commit();

        //closing session
        session.close();


    } catch (Exception e)
    {
        if (transaction != null)
        {
            transaction.rollback();
        }
        e.printStackTrace();
    }
}

public void delete(int userID, Object obj)
{
    Transaction transaction = null;
    try (Session session = HibernateUtil.getSessionFactory().openSession())
    {

        obj = session.load(obj.getClass(), userID);

        // start a transaction
        transaction = session.beginTransaction();

        //deleting the user from the db
        session.delete(obj);

        // commit transaction
        transaction.commit();

        //closing session
        session.close();


    } catch (Exception e)
    {
        if (transaction != null)
        {
            transaction.rollback();
        }
        e.printStackTrace();
    }
}
}

【问题讨论】:

  • 您手写 DAO 而不是使用 Spring Data JpaRepository 自动为您完成这一切是否有特定的原因?
  • 但是当我使用 JpaRepository 执行此操作时,是否可以更简单地测试 Service 类,然后我将在其中使用 CRUD 操作?我还看到了 2 个变体:CrudRepository 和 JpaRepository。 2.另外,你将如何测试CRUD操作呢?
  • (2) 通常,您不测试框架代码——您相信 Spring Data 开发人员已经对其进行了测试并使其正常工作。 (1) 您可以阅读有关详细信息的文档,但 JpaRepository 更具体,尤其适用于您使用多个 Spring Data 后端(例如,JPA 和 MongoDB)并且需要明确路由查询的位置。 (并且存储库抽象使测试变得非常容易,因为您可以直接模拟存储库。)

标签: java spring hibernate get


【解决方案1】:

您阅读的有关测试 DAO 的内容是正确的方法。
不要使用 Mockito 测试 DAO/存储库层。

您不想编写一个断言确实调用了语句流的单元测试:

// start a transaction
transaction = session.beginTransaction();

// add the user object
session.save(obj);

// commit transaction
transaction.commit();

//closing session
session.close();

编写这种测试意味着主要编写模拟来描述流程。
没有价值,因为它在逻辑/行为方面没有检查任何内容。
同样,断言查询是无用的。您可以在 DAO 中编写“SELECT SELECT SELECT”作为查询,如果您依赖检查查询文本,您的测试仍然可以成功。

您使用 Spring。如果你也使用 Spring Boot,你应该依赖 @DataJpaTest 测试切片,它专注于测试数据访问组件。
否则,别担心。我们在 Spring Boot 之前就做到了。所以我们仍然可以做到。
为您的测试配置内存数据库(例如 H2),并根据测试方法清除/填充数据。
例如:

@Autowired
UserDAO userDAO;

@Test
public void getUser_retrieves_users_added_by_addUser(){
    User addedUser = userDAO.add(new User("foo", "bar"));
    // ... flush data in the database and clear first cache level to avoid cache using
    User expectedUser =  userDAO.get(addedUser.getId());
   // assert the expected User
}

@Before
public void tearDown(){
   // clear data in the database
}

【讨论】:

  • 嗨,大卫,感谢您的快速回复。我也想过这样做,但我已经有一个我托管的数据库,那么有没有什么方法可以使用原始数据库和回滚功能的组合来测试我的 DAO?而不是使用新的数据库。您还可以澄清内存数据库的含义吗?它只是一个数据库,我必须单独运行我的测试(例如作为 localhost 数据库)而不是使用我的原始数据库?我是否还必须为它创建一个新的 hibernate.cfg.xml 文件,因为我的现在已连接到我的托管数据库。
  • 你好汤姆,不客气。通常,您不想使用应用程序/“原始”数据库,因为您不想用一些数据污染它。除了应用程序和测试可以以并发方式读取/修改数据之外,它会使测试不可重现并且您的应用程序不一致:您不希望这样。内存数据库是一件大事,但是是的,您总结得很好。您可以在 dzone.com/articles/…baeldung.com/spring-testing-separate-data-source 此处查看 Spring 的一些示例
  • 好的,感谢您提供设置内存数据库的建议,这些使测试变得更加容易:)。
猜你喜欢
  • 2015-04-07
  • 2018-11-14
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 2016-03-15
相关资源
最近更新 更多