简体   繁体   English

使用DBUnit集成测试Spring存储库层

[英]Integration testing Spring repository layer with DBUnit

I have been following this very useful blog post by Petri Kainulainen to write integration tests for my Spring repository code using spring-data-jpa and DBUnit. 我一直在关注Petri Kainulainen的这篇非常有用的博客文章,使用spring-data-jpa和DBUnit为我的Spring存储库代码编写集成测试。

I have my bean context XML set up like so 我有这样的bean上下文XML设置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <context:property-placeholder location="file:src/main/webapp/WEB-INF/config/application-test.properties"
        ignore-resource-not-found="false" />

    <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
        <property name="driverClass" value="${db.driver}" />
        <property name="jdbcUrl" value="${db.url}" />
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />
    </bean>
    <bean id="directorRepository" name="directorRepositoryMock" class="org.mockito.Mockito"
        factory-method="mock">
        <constructor-arg value="com.tvfreakz.repository.DirectorRepository" />
    </bean>

</beans>

My dataset XML has the following 我的数据集XML具有以下内容

<!DOCTYPE dataset SYSTEM "my-dataset.dtd">
<dataset>
    <director directorid="1" director="Ridley Scott" />
    <director directorid="2" director="James Cameron" />
    <director directorid="3" director="David Fincher" />
    <director directorid="4" director="Jean-Pierre Jeunet" />
</dataset>

Here's the repository interface 这是存储库界面

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.tvfreakz.model.entity.Director;

@Repository("directorRepository")
public interface DirectorRepository extends JpaRepository<Director, Long> {

  Director findByDirectorId(Long directorId);

}

And my test class is set up like so 我的测试类就是这样设置的

import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.tvfreakz.model.entity.Director;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/config/testMVCContext.xml"})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
  DirtiesContextTestExecutionListener.class,
  TransactionalTestExecutionListener.class,
  DbUnitTestExecutionListener.class })
@DatabaseSetup("testDataset.xml")
public class ITDirectorRepositoryTest {

  @Autowired
  private DirectorRepository repository;

  @Test
  public void testFindByDirectorIdWhenNoDirectorFound() {
    Director director = repository.findByDirectorId(10L);
    assertNull(director);
  }

  @Test
  public void testFindByDirectorIdWhendirectorIsFound() {
    Director director = repository.findByDirectorId(1L);
    assertEquals("Ridley Scott", director.getDirectorName());
  }

}

I was expecting the @DatabaseSetup annotation to take my configuration and set up all the tables and data inserts into my test database configured by the dataSource bean. 我期待@DatabaseSetup注释采用我的配置并将所有表和数据插入到我的由dataSource bean配置的测试数据库中。

This seemingly does nothing (ie the database remains blank with no tables or data) and my second test testFindByDirectorIdWhendirectorIsFound fails as the director returned is null. 这似乎什么也没做(即数据库保持空白,没有表或数据),我的第二个测试testFindByDirectorIdWhendirectorIsFound失败,因为导致返回的是null。 What am I missing? 我错过了什么?

EDIT 1 OK I have some progress, I now have tables created, BUT no data. 编辑1好我有一些进展,我现在有表创建,但没有数据。 The issue was I shouldn't have used a mock repository. 问题是我不应该使用模拟存储库。 I had to update my context XML to the following. 我不得不将我的上下文XML更新为以下内容。 So the next issue is to try and work out why it isn't filling my newly created tables with data 因此,下一个问题是尝试找出为什么它没有用数据填充我新创建的表

EDIT 2 JpaTransactionManager bean and tx annotation driven added to context 编辑2 JpaTransactionManager bean和tx注释驱动添加到上下文

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <context:property-placeholder location="file:src/main/webapp/WEB-INF/config/application-test.properties"
        ignore-resource-not-found="false" />

<jpa:repositories base-package="com.tvfreakz.repository" />

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="punit"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true"/>
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <entry key="hibernate.hbm2ddl.auto" value="update"/>
            <entry key="hibernate.format_sql" value="true"/>
            <entry key="hibernate.show_sql" value="true"/>
        </map>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
        <property name="driverClass" value="${db.driver}" />
        <property name="jdbcUrl" value="${db.url}" />
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />
    </bean>

</beans>

EDIT 3 OK I managed to enable DEBUG level after including slf4j in my maven dependencies and creating a log4j.properties file with DEBUG level set. 编辑3确定在我的maven依赖项中包含slf4j并创建了一个设置了DEBUG级别的log4j.properties文件后,我设法启用了DEBUG级别。

And I see this in the log, which perhaps gives a clue? 我在日志中看到了这一点,这或许给出了一个线索?

14:47:05,670  INFO TestContextManager:242 - Could not instantiate TestExecutionListener [com.github.springtestdbunit.DbUnitTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/dbunit/dataset/IDataSet]

I believe this is in reference to this part of my test code 我相信这是参考我测试代码的这一部分

@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
  DirtiesContextTestExecutionListener.class,
  TransactionalTestExecutionListener.class,
  DbUnitTestExecutionListener.class })

Along with the edits I made to the original post it seems I was missing the DBUnit dependency in my Maven pom.xml. 随着我对原始帖子的编辑,似乎我在Maven pom.xml中缺少DBUnit依赖项。 After adding the following I now have data, thank you Petri and Phil for your help! 添加以下内容后,我现在有了数据,感谢Petri和Phil的帮助!

    <dependency>
        <groupId>org.dbunit</groupId>
        <artifactId>dbunit</artifactId>
        <version>2.5.0</version>
    </dependency>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM