2

I use JPA/Hibernate for my Spring boot app. I'm writing ftests for the REST controllers.

I want to alter the db state (insert some rows, etc) and test the REST controller to see if it returns/works as expected.

It doesn't sound right to use the Service layer to initialize the database (at the end that's what we want to test as it's an end-to-end test!).

What is the best way to initialize database in a test for Spring boot app?

Note I've heard of DBUnit but it uses xml, and I'd rather use java code.

1 Answer 1

4

I know of three options here

1. import.sql in Hibernate

It's as simple as adding an import.sql to your src/test/resources folder. Inside import.sql you can type in your sql to insert data you want. You would also have to set hibernate-ddl-auto to create in application.properties.

eg. Application.properties

spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.url=jdbc:postgresql://localhost/asgard
spring.datasource.username=thor
spring.datasource.password=mjolnir

eg import.sql

insert into 
    account  (id, createddate, modifieddate, password , username, disabled) 
    values (-1, now(),null, 'password','admin',false);

2. Spring Test DB Unit

Spring Test DB Unit is DB Unit specifically for Spring. This basically lets you add data and remove it after test on method as well as class level which is very useful. Check the link for more details. The xml actually makes it easier to manage the data you want to insert. You can also insert data programatically but it's more complicated and instructions should be there on the website.


@Test
@DatabaseSetup(value = "insert.xml")
@DatabaseSetup(connection="customerDataSource", value="insert-custs.xml")
public void testInsert() throws Exception {
    // Inserts "insert.xml" into dataSource and "insert-custs.xml" into customerDataSource
    // ...
}

eg insert.xml

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <Person id="0" title="Mr" firstName="Phillip" lastName="Webb"/>
</dataset>

Table name is person along with id,title,firstName and lastName as fields.

3. Using @Before annotation

Using @Before annotation in Test class to set up db.

GenericTest Class

@RunWith(SpringRunner.class)
@SpringBootTest
public class GenericTest {

    public EmployeeRepository employeeRepository;

    @Before
    public void setUp() {
        employeeRepository.save(createRandomEmployeeObject());
    }

    @Test
    public void insertSuccess(){
        List<Employee> employee = employeeRepository.findAll();

        //Logic to get employee from rest API

        //Assert if data from rest API matches one in db

    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

it is still using sql, not java, which is not very different from xml from my point of view. I want to be able to compare the actual values with expected values (those inserted in to the db, which lives in the sql file). Therefore I prefer to alter the db with java code, not xml or sql
@ArianHosseinzadeh the xml is for intitial data set up, you just use controllers/service layer in the tests
I know, but in assertions, I compare what was inserted into the db with what is returned by the REST controller. right ? the inserted values in the db, are actually in the sql file.
@ArianHosseinzadeh I have added a 3rd option of using @Before annotation on test class. Is that what you want?
@user2049132 That was what I thought about too. But there's a problem here. Sometimes, calling repository from a class not annotated with @Transactional causes some issues. Does it make sense to annotate a test class with @Transactional ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.