I have the following table (migration):
databaseChangeLog:
- changeSet:
id: 1
author: me
changes:
- createTable:
tableName: person
columns:
- column:
name: id
type: int
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: first_name
type: varchar(255)
constraints:
nullable: false
- column:
name: last_name
type: varchar(255)
constraints:
nullable: false
- changeSet:
id: 2
author: me
changes:
- insert:
tableName: person
columns:
- column:
name: first_name
value: First
- column:
name: last_name
value: Last
And the following DAO:
public interface HelloDao {
@SqlQuery(
"SELECT * FROM person"
)
@Mapper(PersonMapper.class)
Person getPerson();
}
With the following entities + mapper:
public class Person {
private String firstName;
private String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
-
public class PersonMapper implements ResultSetMapper<Person> {
public Person map(int index, ResultSet r, StatementContext ctx) throws SQLException {
return new Person(r.getString("first_name"), r.getString("last_name"));
}
}
I'm using junit and unitils to write a unit test for this Dao. I have the unitils.properties
file set up like so:
database.driverClassName=org.postgresql.Driver
database.url=jdbc:postgresql://localhost:5432/springbootdb
database.dialect=postgresql
database.userName=<username>
database.password=<password>
database.schemaNames=public
Just for clarity, this my application.properties
file:
spring.thymeleaf.cache=false
spring.main.show-banner=false
logging.level.jdbc=OFF
logging.level.jdbc.sqltiming=DEBUG
logging.level.jdbc.resultsettable=DEBUG
spring.datasource.url= jdbc:postgresql://localhost:5432/springbootdb
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.jpa.hibernate.ddl-auto=create-drop
Here is my test:
@Transactional(TransactionMode.ROLLBACK)
@RunWith(UnitilsBlockJUnit4ClassRunner.class)
public class HelloDaoTest {
@TestDataSource
DataSource dataSource;
private DBI dbi;
private HelloDao helloDao;
@Before
public void setUp() throws Exception {
dbi = new DBI(dataSource);
helloDao = dbi.onDemand(HelloDao.class);
}
@Test
@DataSet("HelloDaoTest.testSet.xml")
public void helloDao() throws Exception {
Person p = helloDao.getPerson();
assertEquals("First", p.getFirstName());
}
}
And my fixture (HelloDaoTest.testSet.xml
)
<?xml version="1.0" encoding="UTF-8" ?>
<dataset>
<person
first_name="First"
last_name="Last"
/>
</dataset>
and the pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.experiment.springboot</groupId>
<artifactId>testspringbootproj</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring Boot Blank Project (from https://github.com/making/spring-boot-blank)</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.7.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.experiment.springboot.App</start-class>
<java.version>1.8</java.version>
<lombok.version>1.14.8</lombok.version>
<log4jdbc.log4j2.version>1.16</log4jdbc.log4j2.version>
<rest.assured.version>2.3.3</rest.assured.version>
<jdbi.version>2.78</jdbi.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest.assured.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
<version>${log4jdbc.log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1206-jdbc42</version>
</dependency>
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi</artifactId>
<version>${jdbi.version}</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.unitils</groupId>
<artifactId>unitils-dbunit</artifactId>
<version>3.4.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>${spring-loaded.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
</plugins>
</build>
</project>
When I run this test I get the following error:
java.lang.NullPointerException
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:820)
at org.unitils.database.transaction.impl.DefaultUnitilsTransactionManager.rollback(DefaultUnitilsTransactionManager.java:157)
at org.unitils.database.DatabaseModule.rollbackTransaction(DatabaseModule.java:425)
at org.unitils.database.DatabaseModule.endTransactionForTestMethod(DatabaseModule.java:390)
at org.unitils.database.DatabaseModule$DatabaseTestListener.afterTestTearDown(DatabaseModule.java:486)
at org.unitils.core.Unitils$UnitilsTestListener.afterTestTearDown(Unitils.java:315)
at org.unitils.core.junit.AfterTestTearDownStatement.evaluate(AfterTestTearDownStatement.java:48)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.unitils.core.junit.BeforeTestClassStatement.evaluate(BeforeTestClassStatement.java:41)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
It looks like the test code is not even reached. What am I doing wrong?
You do have two database implementations in your pom.xml, without specifying scopes. Spring is not able to guess which one shall be the right one, hence an exception.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
[...]
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1206-jdbc42</version>
</dependency>
Most likely this will help you further: Configure specific in memory database for testing purpose in Spring
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With