If you are struggling to write good automated tests, you are not alone.

Spring Data JPA Tutorial: Integration Testing

Exam

My Spring Data JPA tutorial has taught us that we can create database queries and persist entities in the database by using special repository interfaces.

This raises an interesting question:

How can we write integration tests for our Spring Data JPA repositories because they are just interfaces?

This blog post answers to that question. During this blog post we will write integration tests for a Spring Data JPA repository that manages the information of todo entries (Todo objects). To be more specific, we will write integration tests for the findBySearchTerm() method of TodoRepository interface. That method ignores case and returns todo entries whose title or description contains the given search term.

Let’s start by getting the required dependencies with Maven.

There are two things that you should know before you read this blog post:

  • If you are not familiar with Spring Data JPA, you should take a look at my Spring Data JPA Tutorial before you continue reading this blog post.
  • If you want to write integration tests for Spring powered repositories that do not use Spring Data JPA, you can still use the approach described in this blog post.

Getting the Required Dependencies With Maven

We can get the required dependencies with Maven by declaring the following dependencies in our pom.xml file:

  • JUnit (version 4.11).
  • AssertJ Core (version 3.2.0). We use AssertJ for ensuring that the tested method returns the correct information.
  • Spring Test (version 4.1.6.RELEASE).
  • DbUnit (version 2.5.1). Remember to exclude the JUnit dependency. We use DbUnit for initializing our database into a known state before each test case is invoked.
  • Spring Test DbUnit (version 1.2.1) integrates DbUnit with the Spring Test framework.

The relevant part of our pom.xml file looks as follows:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.11</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.assertj</groupId>
	<artifactId>assertj-core</artifactId>
	<version>3.2.0</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-test</artifactId>
	<version>4.1.6.RELEASE</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.dbunit</groupId>
	<artifactId>dbunit</artifactId>
	<version>2.5.1</version>
	<scope>test</scope>
	<exclusions>
		<exclusion>
			<artifactId>junit</artifactId>
			<groupId>junit</groupId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>com.github.springtestdbunit</groupId>
	<artifactId>spring-test-dbunit</artifactId>
	<version>1.2.1</version>
	<scope>test</scope>
</dependency>

After we have configured the required dependencies in our pom.xml file, we can configure our integration tests.

I just announced my "Test With Spring" course:

GET THE 30% EARLY-BIRD DISCOUNT >>

Configuring Our Integration Tests

We can configure our integration tests by following these steps:

  1. Run integration tests by using the SpringJUnit4ClassRunner class. It is a custom JUnit runner that integrates the Spring Test framework with JUnit. We can configure the used JUnit runner by annotating our test class with the @RunWith annotation.
  2. Configure the application context configuration class (or XML configuration file) that configures the application context used by our integration tests. We can configure the used application context configuration class (or XML configuration file) by annotating our test class with the @ContextConfiguration annotation.
  3. Configure the test execution listeners which react to the test execution events that are published by the Spring Test framework. We have to configure the following test execution listeners:
    • The DependencyInjectionTestExecutionListener provides dependency injection for the test object.
    • The TransactionalTestExecutionListener adds transaction support (with default rollback semantics) into our integration tests.
    • The DbUnitTestExecutionListener adds support for the features provided by the Spring Test DbUnit library.

After we have added this configuration into our integration test class, its source code looks as follows:

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import org.junit.runner.RunWith;
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.transaction.TransactionalTestExecutionListener;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class})
public class ITFindBySearchTermTest {
}

After we have configured our integration test class, we can start writing integration tests for our Spring Data JPA repository.

Writing Integration Tests for Our Repository

We can write integration tests for our repository by following these steps:

First, we have to inject the tested repository into our test class. Because we are writing integration tests for the TodoRepository interface, we have to inject it into our test class. The source code of our test class looks as follows:

import com.github.springtestdbunit.DbUnitTestExecutionListener;
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.transaction.TransactionalTestExecutionListener;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class})
public class ITFindBySearchTermTest {

	@Autowired
	private TodoRepository repository;
}

Second, we have to create the DbUnit dataset that initializes our database into a known state before our test cases are invoked. We will use the flat XML dataset format because it is less verbose than the original DbUnit dataset format. This means that we can create our dataset by following these rules:

  • Each XML element contains the information of a single table row.
  • The name of the XML element identifies the name of the database table in which its information is inserted.
  • The attributes of the XML element specify the values that are inserted into the columns of the database table.

I just announced my "Test With Spring" course:

GET THE 30% EARLY-BIRD DISCOUNT >>

The tested repository (TodoRepository) queries information from the todos table that has the following columns: id, created_by_user, creation_time, description, modified_by_user, modification_time, title, and version.

Because we are writing integration tests for a method that returns a list of Todo objects, we want to insert two rows to the todos table. We can do this by creating a DbUnit dataset file (todo-entries.xml) that looks as follows:

<dataset>
    <todos id="1"
           created_by_user="createdByUser"
           creation_time="2014-12-24 11:13:28"
           description="description"
           modified_by_user="modifiedByUser"
           modification_time="2014-12-25 11:13:28"
           title="title"
           version="0"/>
    <todos id="2"
           created_by_user="createdByUser"
           creation_time="2014-12-24 11:13:28"
           description="tiscription"
           modified_by_user="modifiedByUser"
           modification_time="2014-12-25 11:13:28"
           title="Foo bar"
           version="0"/>
</dataset>
Additional reading:

DbUnit documentation provides more information about the different DbUnit dataset formats.

Third, we can write integration tests for the findBySearchTerm() method of the TodoRepository interface. Let’s write integration tests which ensure that the findBySearchTerm() method is working correctly when the title of one todo entry contains the given search term. We can write these integration tests by following these steps:

  1. Configure the used dataset file by annotating the integration test class with the @DatabaseSetup annotation.
  2. Write an integration test which ensures that the findBySearchTerm() method returns one todo entry when the search term “iTl” is passed as a method parameter.
  3. Write an integration test which ensures that the findBySearchTerm() method returns the “first” todo entry when the search term “iTl” is passed as a method parameter.

The source code of the ITFindBySearchTerm class looks as follows:

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
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.transaction.TransactionalTestExecutionListener;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class})
@DatabaseSetup("todo-entries.xml")
public class ITFindBySearchTermTest {

	@Autowired
	private TodoRepository repository;
	
	@Test
	public void findBySearchTerm_TitleOfFirstTodoEntryContainsGivenSearchTerm_ShouldReturnOneTodoEntry() {
		List<Todo> searchResults = repository.findBySearchTerm("iTl");
		assertThat(searchResults).hasSize(1);
	}
	
	@Test
	public void findBySearchTerm_TitleOfFirstTodoEntryContainsGivenSearchTerm_ShouldReturnFirstTodoEntry() {
		List<Todo> searchResults = repository.findBySearchTerm("iTl");

		Todo found = searchResults.get(0);
		assertThat(found.getId()).isEqualTo(1L);
	}	
}
When you use the @DatabaseSetup annotation, you have to follow these rules:

  • If all test methods of your test class use the same dataset, you can configure it by annotating your test class with @DatabaseSetup annotation. However, if all test methods of your test class do not use the same dataset, you have to annotate your test methods with the @DatabaseSetup annotation.
  • If the dataset file is in the same package than the integration test class, you can configure it by using the name of the dataset file. On the other hand, if the dataset file is not in same the package than the test class, you have to configure the full path of the dataset file. For example, if your dataset file (todo-entries.xml) is in the package foo.bar, you can configure its full path by using the string: “/foo/bar/todo-entries.xml”.

Additional Reading:

Let’s move on and summarize what we learned from this blog post.

Summary

This blog post has taught us four things:

  • We can integrate DbUnit with the Spring Test framework by using Spring Test DbUnit.
  • We can integrate Spring Test DbUnit with the Spring Test framework by using the DbUnitTestExecutionListener class.
  • We should use the flat XML databaset format because it is less verbose than the original DbUnit dataset format.
  • We can use the @DatabaseSetup annotation on the class level or on the method level.

P.S. You can get the example applications of this blog post from Github (query methods, JPA Criteria API, Querydsl).

If you want to learn how to use Spring Data JPA, you should read my Spring Data JPA tutorial.

About the Author

Petri Kainulainen is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.

About Petri Kainulainen →

70 comments… add one
  • I got java.lang.NullPointerException when I attemt to run repository method ,
    object who insance of interface is null .
    How solve it ?

    Reply
  • This tutorial helped me and my team implement unit tests successfully. There are minor things missing in the post (like bonecp inclusion in the pom.xml and the full contents of the Spring context) but the github project helped to fill those.

    Great work and thanks for sharing!

    Reply
    • I am happy to hear that your team found this blog post useful. Also, I left the other dependencies out because I felt that they were out of the scope of this post. However, now that you mentioned this issue, I will update this blog post and add a link to the full pom.xml file. Maybe this will clarify things a bit.

      Reply
  • the useful article, thanks!!

    Reply
    • You are welcome. I am happy to hear that this blog post was useful to you.

      Reply
  • Hi Petri

    Im trying to use spring db unit. The versions I have are the ones recommended above in your blog. However Im encountering (could not find dataset.xml) file
    testController(my.tests.web.TermControllerIntegrationTest) Time elapsed: 4.245 sec <<< ERROR!
    java.lang.IllegalArgumentException: Unable to load dataset from "classpath:/termData.xml" using class com.github.springtestdbunit.dataset.FlatXmlDataSetLoader
    at org.springframework.util.Assert.notNull(Assert.java:112)

    I have tried many things.
    Putting the dataset in the same package as the class.
    in the classpath under resources
    and trying to reference it with'/' like classpath:/termData.xml etc with no luck.
    My unit test works well without db unit.

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

    any help would be very useful.

    Reply
    • Hi Chris,

      If the dataset file is in the same package than your test class, you can reference it by simply using its name (In your case, termsData.xml should work). Also, remember that you have to compile your project every time when you add a new dataset file or modify an existing file (this sucks btw).

      Reply
  • Can you give me an example to write @Query for Join operation ? Iam struggling with the error called “unexpected token:” error – @Query(select count(*) from employee emp join employeedetaildata edd on emp.id=edd.employeedataid where emp.rankId = :rankId)

    Reply
  • Hi Petri,

    thanks for your great Spring Data JPA tutorials. I just started to use DbUnit in one of my private applications but I get this warning every time DbUnit sets up the database via @DatabaseSetup:

    WARN org.dbunit.dataset.AbstractTableMetaData – Potential problem found: The configured data type factory ‘class org.dbunit.dataset.datatype.DefaultDataTypeFactory’ might cause problems with the current database ‘H2’ (e.g. some datatypes may not be supported properly). In rare cases you might see this message because the list of supported database products is incomplete (list=[derby]). If so please request a java-class update via the forums.If you are using your own IDataTypeFactory extending DefaultDataTypeFactory, ensure that you override getValidDbProducts() to specify the supported database products.

    Relevant test dependencies:
    org.springframework:spring-test:4.0.2
    com.github.springtestdbunit:spring-test-dbunit:1.1.0
    org.dbunit:dbunit:2.4.9
    com.h2database:h2:1.3.175

    The only difference to your setup is, that I override the DataSource of my default application config in the test config via:

    @Bean
    public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
    }

    But that should not be the problem. I am able to suppress the warning via logging configuration but maybe you know another way to solve this “problem” (all test run fine)?

    Best regards,
    Patrick

    P.S.: Have you already recognized the new Hikari Connection Pool (HikariCP) as alternate to BoneCP? Though I haven’t benchmarked the connection pool myself yet, it definitely feels faster than BoneCP to me and the benchmarks on the HikariCP web page promise an outstanding performance.

    Reply
    • Hi Patrick,

      Thank you for your kind words! It is nice to hear that my tutorials have been useful to you.

      I assume that this line is written to the log because the default DbUnit data type factory doesn’t support vendor specific data types. I am not 100% sure about this but it seems like a reasonable assumption (my assumption is based on this DbUnit FAQ entry).

      If my assumption is correct, you have to configure DbUnit to use the H2DataTypeFactory instead of the DefaultDataTypeFactory. When you use Spring Test DBUnit, you can do this adding the DatabaseConfigBean (configure the data type factory by calling the setDatatypeFactory() method) and DatabaseDataSourceConnectionFactoryBean beans to the application context (more about this here. Search for Custom IDatabaseConnections text).

      I haven’t done this myself because I haven’t been using vendor specific data types but based on the documentation, it should do the trick. By the way, I figured this out after I read this answer to a similar Stack Overflow question.

      I haven’t used HikariCP myself but I ran its data source benchmark this week, and HikariCP seems to be a lot faster than BoneCP. I am going to try it in the example applications of my new blog entries. It will be interesting to see if I notice any difference.

      Reply
      • Hi Petri,

        thanks for your quick reply. I solved the warning by using this configuration: https://gist.github.com/PatrickGotthard/9558923

        Regards,
        Patrick

        Reply
        • Hi Patrick,

          you are welcome. Your configuration looks simple and I am going to use the same approach in my new blog posts. Thanks for sharing it.

          Reply
          • Hi again,

            are you interested to be notified when I push the project to GitHub? Maybe we could exchange some knowledge based on the projects sources.

          • Hi,

            sure. Let me know when you do that (push the project to Github). I think it would be a good opportunity to learn something new (for both of us).

          • Hi Petri,

            I have pushed my project to GitHub now: https://github.com/PatrickGotthard/newsreadr-server

            Feel free to look at the sources (especially the integration tests). I would be really happy to get some input from you.

            You would have to check out https://github.com/PatrickGotthard/newsreadr-bom and https://github.com/PatrickGotthard/newsreadr-shared as well to import the project into your IDE (currently there are no public Maven snapshots available but I would configure my Jenkins and Nexus soon).

            Regards,
            Patrick

          • Hi Patrick,

            Cool! I will take a look at that project later this week (and give feedback of course).

          • Update: the transitive dependencies are now public available so that you don’t have to check out the related projects. I’ve also added installation and build instructions to get started.

          • I just cloned the Github repository and started playing with the code. I will email my thoughts to you when I am finished.

  • nice post, would i ask for an example on how to test model data ?
    I want to test a controller request method that initiate the model data,
    also is it possible to test thymeleaf templates ?

    Thanks in advance

    Reply
    • You should check out my Spring MVC Test Tutorial. It explains how you can write both unit and integration tests for your Spring MVC controllers.

      Also, It is possible to test Thymeleaf templates by using the Spring MVC Test framework. I haven’t written anything about this because I haven’t had the chance to use Thymeleaf. However, this blog post has a small description about this, and it seems that writing tests for Thymeleaf templates is pretty simple. All you have to do is to write assertions for the response body.

      Reply
  • Very great blog. Good explanation.
    Thank you!

    Reply
    • You are welcome. I am happy to hear that this blog post was useful to you.

      Reply
  • Nice post. Can I ask : How can I write integration test cases (testing from request to response) on my spring mvc app which uses spring data jpa – without changing the state of the oracle database ? Can I somehow fetch the required tables and their data into an in memory database for testing purposes ?
    I have never used it but DBUnit seems less configurable for complex data sets and I don’t want to write xml files for data sets. AND it doesn’t create in memory HSQLDB tables either. What other options do I have ?

    Reply
    • The example application of this blog has two profiles: dev and integration-test. Both of these profiles use H2 in-memory database but in a real life scenario, only the integration-test profile would be using it (the other profiles would use a “real” database).

      I have configured Hibernate to create the database tables by setting the value of the hibernate.hbm2ddl.auto property to create-drop.

      If you take a look at the config.properties file used when the integration-test Maven profile is activated, you will find the following line from it:

      
      hibernate.hbm2ddl.auto=create-drop
      
      

      This line ensures that the Hibernate creates the database for my integration tests. After the database has been created, I insert the test data by using DbUnit. All example applications of my Spring MVC Test tutorial use the same approach.

      I agree that the DbUnit can be a tricky beast to configure and large data sets are pain in the ass (that is why they should be avoided). However, I haven’t been able to find any alternatives to it. If you happen to find one, let me know!

      Reply
  • Hello,

    I tried following the tutorial. Unfortunately I hit into an error “Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type”.

    My implementation can be found at https://gist.github.com/rashidi/34f7f0dc70da92de1a1b. I am using gradle instead of maven.

    Also, I placed the test class inside src/test instead of src/main. I tried moving it to src/main but it still failed with the same error.

    Thanks in advanced for your help! :D

    Reply
    • Hi,

      it seems that you forgot to configure Spring Data JPA, and that is why the Spring container cannot find the repository bean (and throws an exception). You can fix this by annotating your configuration class with the @EnableJpaRepositories annotation (remember to set the value of its basePackages attribute).

      By the way, if you want to use annotation driven transaction management, you have to annotate your configuration class with the @EnableTransactionManagement as well.

      I hope that this answered to your question.

      Reply
  • Thanks for the excellent posts on spring jpa. Helped me learn a lot about them.

    After going through your other Spring JPA Tutorials, I successfully implemented it in a Sprin MVC application. Everything works fine.

    However, now I’m trying to learn to write integration test cases based on the above tutorial. When I run the test, I get the exception ” Injection of autowired dependencies failed;” for the Autowired Repository.

    What could possibly be wrong here when the application is successfully running when tested from the front-end.

    Thanks a lot in advance.

    PS: I use XML based configuration. and I’ve included the below for the jpa repositories in the XML Configuration.

    Regards,
    Basu

    Reply
    • Hi,

      It seems that Wordpress ate your XML configuration. Anyway, typically the root cause of your problem is that the Spring container couldn’t either create the repository OR it just didn’t find it (check the stacktrace for more details).

      The first case often happens when there is a problem in the configuration, and the second case happens the repository base package is incorrect.

      It would be helpful to see your integration test, repository interface, and the application context configuration file. Maybe you could add these files to pastebin? Also, the full stacktrace would be really helpful because you can find the root cause of the problem by reading it.

      Reply
  • Hello Perti,

    I am following your series and using JavaConfig approach.
    I am getting below error. Could you please give some hint why this is happening.

    Many thanks
    Sanjeev.

    Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1069)
    … 45 more

    Reply
    • Thanks,
      The error is gone, After I removed the following annotations from the PersistenceContext class.

      
      @Configuration
      //@ComponentScan
      //@EnableJpaRepositories 
      //@EnableTransactionManagement
      //@EnableWebMvc 
      //@EnableEnableAutoConfiguration
      //@ImportResource("classpath:applicationContext.xml")
      @PropertySource(value = { "classpath:application.properties" })
      class PersistenceContext { ...}
      
      
      Reply
      • This might be a class loading issue. I noticed that your PersistenceContext class was annotated with the @EnableAutoConfiguration annotation. I assume that you are using Spring Boot. Right?

        If this is the case, you should ensure that you don’t have older Spring versions in your classpath. Check out section 9.1.1 Maven Installation of the Spring Boot reference manual for more details about this.

        Reply
  • Hi Petri,
    When Spring data JPA check for correct database url.
    I need to catch the same in exception if database connectivity fails.

    Reply
    • Hi Sumit,

      • If your database url doesn’t follow the correct syntax, SQLException is thrown when your application is started. For example, you might see an error message like this your log file: Caused by: java.sql.SQLException: No suitable driver found for jbc:mysql://localhost:3306/socialtwitter
      • If your database url follows the correct syntax, but your application cannot open a database connection, it throws an exception when it tries to open a database connection.

      What kind of an error handler you want to implement?

      If you want to just redirect the user to an error page when your application cannot open a database connection, you should take a look at the Javadoc of the SimpleMappingExceptionResolver class.

      If you want to learn how you can handle exceptions with Spring MVC, you should read a blog post titled: Exception Handling in Spring MVC.

      Reply
  • ¿why I can not use ?
    Please respond to my email

    Reply
    • I send an email to you.

      Reply
  • Hi Petri,

    I have a question for you regarding development process. I have been reading through a number of your very useful posts. My process so far (using TDD) is for example to develop Controller test A (using a mock service as you have done), have it fail, flesh out the controller method A have that pass.

    Then move on to writing service test A (using a mock repository), have it fail, then flesh out the service method A and have that pass.

    Then go back through the same process with test B, test C etc.

    Once the unit tests have a good coverage for the Controller and Service layers, I can then move on to writing integration tests for the Repository layer as you have done here. Is this similar to the process you follow?

    Thanks,
    Paul

    Reply
    • Hi Paul,

      I have actually written a blog post that describes the process which I am using the moment. But I will save you from reading it by telling that I use the same process than you do. Also, after I have finished writing integration tests for my repositories, I write integration tests for my controllers (I guess you can call these end-to-end tests as well).

      Reply
  • Hi Petri,

    I finally got round to trying this out and I am having some problems with the database setup not working. Instead of typing this all out again I have made a stack overflow post here

    http://stackoverflow.com/questions/28043618/integration-testing-spring-repository-layer-with-dbunit

    If you have some time would you be able to take a look and see if you can spot where I’m going wrong?

    Thanks,
    Paul

    Reply
    • Hi Paul,

      I left a comment to your StackOverflow question and asked a few additional questions that will help me to write a better answer for you.

      Reply
      • Thanks, I’ve also replied with some progress. I now have tables, but no data, so the second test still fails as it doesn’t return the expected result

        Reply
      • It’s perhaps something to do with the TestExecutionListener, I have this message in my log. Any ideas?

        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]

        Reply
        • I will take a look at this later today (I have to work for few hours), but I think that you have found the smoking gun. Which Spring version are you using?

          Reply
          • Thanks, I’m using 4.0.6

          • Unfortunately I could not reproduce your problem :( Are you using the latest versions of Spring Test DbUnit (1.1.0) and DbUnit (2.5.0)?

            I assume that you are using the latest versions because Spring Framework 4.0 is not compatible with Spring Test DbUnit 1.0.0, and if you try to use it, your tests fail because an exception is thrown.

            You could try to take a look at this example application and compare its configuration with your configuration. Note that the XML configuration is not working at the moment. I will try to fix it tomorrow.

          • Gah! That was it, I was missing the DBUnit dependency! Silly mistake! Thanks for your time Petri!

          • Great! It is good to hear that you were able to solve your problem. If you want to find out what kind of tests I write for my data access code, you should read my Writing Tests for Data Access Code tutorial.

  • Thanks, Petri.
    These days I’m in JPA&TDD develop study. Your post is always helpful.
    ^0^

    Reply
  • Hi Petri, is this tutorial also work for Spring Boot?

    Reply
    • Yes, but you have to make minor changes to the configuration (use the @SpringApplicationConfiguration annotation instead of the @ContextConfiguration annotation). The section 35.3 Testing Spring Boot Applications of the Spring Boot Reference Manual provides more information about this.

      P.S. I haven’t tried writing tests for Spring Boot applications, but I cannot figure out any reasons why this wouldn’t work.

      Reply
      • Also, is it possible to see the SQL statement used by dbunit when the database is populated from the XML dataset?

        Reply
        • DbUnit writes the invoked prepared statements to the log file by using the DEBUG log level. If you need to see the actual SQL statements, you can use log4jdbc.

          Reply
  • hi petri,
    how to mock test the below interface.
    ========================

    
    public abstract java.lang.Iterable save(java.lang.Iterable arg0);
    
    

    ========================
    i want to batch update an repo , which has 200 records .
    i wan to batch update it with a loop of 20 records in one save.which is the best approach to flush the repository.

    i am using this below startegy is this ok .
    ist of repository object -modelListPersist

    
    int count=0;
      
    while ( count< modelListPersist.size() ) {
    	model model = (model) modelListPersist.get(count);
    	modelRepository.save(model);
    	if ( ++count % 20 == 0 ) {
    		//flush a batch of updates and release memory:
    		modelRepository.flush();            	
    	}
    }
    
    
    Reply
    • Hi Sathish,

      Before I can help you to mock the model repository, I have to understand what kind of an test do you want to write. For example:

      • Do you want to ensure that correct Model objects are saved to the database?
      • Do you want to ensure that the changes are flushed after 20 objects have been processed?
      Reply
  • I cannot use it inside my real world project, you are pointing to stuff at Github! please post pure solutions! we cannot use it if it points to GitHub third party stuff!

    Reply
    • Do you have a company policy that prevents you from using 3rd party frameworks or libraries hosted on Github? If so, I feel sorry for you.

      However, I will continue using these frameworks and libraries in my examples for two reasons:

      1. I don’t want to write a worse version of an existing library or framework.
      2. These libraries and frameworks help me to save time. This is extremely valuable because my time is a limited resource.

      P.S. You should read this blog post: Using a framework or not?

      Reply
  • Do you have any video tutorial?

    Reply
  • Hi Petri,

    Great article, I am trying to use this information to test a sample project I have got from the internet. https://github.com/netgloo/spring-boot-samples/tree/master/spring-boot-mysql-springdatajpa-hibernate

    I have added a PersistanceContext but alot of the information in there references db.url when the properties file uses “spring.datasource.url” shall I change this in the PersistanceContext?

    Reply
    • Hi Steve,

      If you are trying to write integration tests for a repository that is configured by Spring Boot, you need to configure your integration tests by following the advice given in the Spring Boot Reference Documentation.

      Also, you don’t need to add the PersistenceContext class because Spring Boot should configure the persistence layer of your application.

      If you have any additional questions, don’t hesitate to ask them!

      Reply
      • Thanks for the quick reply.

        I have a user-entries.xml that contains:

        Is this still needed to represent the dummy data?
        `I have added @ContextConfiguration({“classpath:/user-entries.xml”})`
        to load it if I do.

        and then tried to run the test, I am getting an exception:
        java.lang.IllegalStateException: Failed to load ApplicationContext
        at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
        at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
        at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)

        Thanks

        Reply
        • Hi Steve,

          If you want to initialize your database into a known state before your test methods are invoked, you need to configure the used dataset by using the @DatabaseSetup annotation. You can use this annotation on class level or method level. Also, remember to follow the rules described in this blog post.

          Reply

Leave a Comment