内存中带有 derby 的单元测试数据库层 DAO

Posted

技术标签:

【中文标题】内存中带有 derby 的单元测试数据库层 DAO【英文标题】:Unit Testing database layer DAO with derby in memory 【发布时间】:2013-10-24 23:51:42 【问题描述】:

我想用这个对我的 DAO 实现进行单元测试:

public class BaseDAOImplTest 

    private EntityManagerFactory emFactory;
    private EntityManager em;
    private static Logger logger = Logger.getLogger(BaseDAOImplTest.class
            .getName());

    @Before
    public void setUp() throws SQLException, ClassNotFoundException 

        logger.info("Starting in-memory database for unit tests");

        try 

            //Creating testDB database
            Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
            DriverManager.getConnection("jdbc:derby:memory:TestingDB;create=true");
            logger.info("Building JPA EntityManager for unit tests");

            //Creating Entity Manager
            emFactory = Persistence.createEntityManagerFactory("TestingDB");
            em = emFactory.createEntityManager();
         catch (ClassNotFoundException e) 

            e.printStackTrace();
        
    

    @Test
    public void testPersistExcursion() 
        BaseDAOImpl baseDao = new BaseDAOImpl(Excursion.class, em);
        Calendar c = Calendar.getInstance();
        c.set(2013, 8, 24);
        Excursion ex1 = createExcursion(c.getTime(), 10, "Simple excursion 1", "New York", 35);
        ex1 = baseDao.persist(ex1);
        assertEquals(baseDao.findById(ex1.getId()), ex1);
    

    @Test
    public void testPersist() 
        try 
            Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
            String dbURL = "jdbc:derby:memory:TestingDB;create=true";
            Connection conn = getConnection(dbURL);
            EntityManagerFactory f = Persistence.createEntityManagerFactory("TestingDB");
            EntityManager em = f.createEntityManager();
            BaseDAOImpl b = new BaseDAOImpl(Excursion.class, em);
            Calendar c = Calendar.getInstance();
            c.set(2013, 8, 24);
            Excursion ex1 = createExcursion(c.getTime(), 10, "Simple excursion 1", "New York", 35);
            ex1 = b.persist(ex1);
            assertEquals(b.findById(ex1.getId()), ex1);
         catch (ClassNotFoundException ex) 
            Logger.getLogger(BaseDAOImplTest.class.getName()).log(Level.SEVERE, null, ex);
        
    

testPersist 正在工作,结果是此测试通过。但是在testPersistExcursion 中,NullPointerException 出现错误,因为在setUp 上,我得到:

java.lang.ClassNotFoundException: org.apache.derby.jdbc.EmbeddedDriver

我只想将EntityManager 添加为全局并在setUp 中初始化,因此我不需要在每个单元测试中再次编写这些行(我在一些文章中看到它,我认为这是一个很好的方法)。但这有什么问题?为什么它在单元测试中工作但在setUp 我找不到那个驱动程序?谢谢

编辑:

我发现了问题,那是在 Maven 中。我有错误的 artifactId。但现在我在这一行遇到了"Unable to build EntityManagerFactory" 的问题:emFactory = Persistence.createEntityManagerFactory("TestingDB");

我的持久化单元:

<persistence-unit name="TestingDB" transaction-type="RESOURCE_LOCAL">
    <class>cz.infi.javatravelagency.entities.Reservation</class>
    <class>cz.infi.javatravelagency.entities.Trip</class>
    <class>cz.infi.javatravelagency.entities.Customer</class>
    <class>cz.infi.javatravelagency.entities.Excursion</class>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.connection.username" value="APP"/>
      <property name="hibernate.connection.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
      <property name="hibernate.connection.password" value="APP"/>
      <property name="hibernate.connection.url" value="jdbc:derby:memory:TestingDB;create=true"/>
      <property name="hibernate.connection.autoReconnect" value="true" />  
      <property name="hibernate.connection.autoReconnectForPools" value="true" />  
      <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />  
    </properties>
  </persistence-unit>

【问题讨论】:

您的应用程序(非测试)数据源是如何配置的?通过persistence.xml?应该(我认为)可以在 src/test/resources 下创建另一个persistence.xml ...有关示例,请参见此处murraywilliams.com/2012/04/maven-and-jpa-programming。我假设您没有使用 Spring,它提供了一些进一步的选择。 是的,坚持不懈,我没有使用 Spring,因为它将处于下一个里程碑。我正在做这个作为家庭作业。我会看看那篇文章谢谢。 如果您使用的是 Maven,您可以查看我对这篇 SO 帖子的回答并使用 derby-maven-plugin:***.com/questions/14731178/…。 【参考方案1】:

好的,根据我的评论,我已经尝试过了,它按预期工作。运行测试时,src/test/resources/META-INF 中的测试特定 persistence.xml 会按预期获取。

然后您可以创建一个 BaseDao 类,其中包含以下几行:

public class BaseDao 

    private static EntityManagerFactory emf;

    public static EntityManager getEntityManager() 

        if (emf == null) 

            emf = Persistence.createEntityManagerFactory("test");
        

        return emf.createEntityManager();
    

哪个更好!

【讨论】:

以上是关于内存中带有 derby 的单元测试数据库层 DAO的主要内容,如果未能解决你的问题,请参考以下文章

使用 H2 数据库对 DAO 层进行单元测试

如何在 Java 中对 DAO 应用单元测试

DAO层单元测试编码和问题排查

使用 Mockito 对 DAO 层进行单元测试

dao层单元测试报错CONDITIONS EVALUATION REPORT

在 Spring Boot 中使用 Hibernate 为 DAO 层配置单元测试