简体   繁体   中英

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.

I have my bean context XML set up like so

<?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

<!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.

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. What am I missing?

EDIT 1 OK I have some progress, I now have tables created, BUT no data. The issue was I shouldn't have used a mock repository. I had to update my context XML to the following. 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

<?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.

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. After adding the following I now have data, thank you Petri and Phil for your help!

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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