Write component tests for SpringBoot application using OpenTable Embdedded Postgres

I would like to share with you my experience on writing a component test for SpringBoot application using OpenTable embedded Postgres database. I am using Liquibase for database migration. A prior basic understanding of Spring Boot framework is expected from the reader.

For this experiment, I am using:

The primary focus of this article is to help those poor souls who are in search of a simple and useful article on writing component tests using embedded Postgres database that runs against Liquibase. I have used H2 database previously. I was not very happy with the outcome since I had some unpleasant experiences of the tests passing, but the database migration failing whilst running the migration scripts against a real database. The use of PostgreSQL Test container is another option. Although this is a great approach, sometimes you may be constrained only to use an in-memory option. This happens when your client/employer is using an operating system that is not very Docker friendly. Believe me, this is 2020 and there are companies who are still using Windows 7 operating system!

Architecture diagram

architecture

Architecture diagram explained

    <dependency>
        <groupId>com.opentable.components</groupId>
        <artifactId>otj-pg-embedded</artifactId>
        <version>0.13.1</version>
        <scope>test</scope>
    </dependency>

The line of code EmbeddedPostgres.builder().start() starts embedded postgres database at a random port.
Unlike H2, OpenTableEmbedded Postgres database can make the component tests slow, especially when there are a large number of tests to run. To speed up the tests, I have added a check to start the database only if the database is not started yet. This will start the database only once for the entire test suite run.

@LocalServerPort
private int applicationPort;

I have injected the data-source in the component test class. This is for loading the test data. This is an optional thing to do and will only be needed if the database pre-population is necessary.

@Autowired
@Qualifier("embeddedPostgresDataSource")
private DataSource dataSource;

In the test, I call the method executeDBQuery(dataSource, INSERT_BOOKS) that loads book data into the embedded database. When the GET /books endpoint is called, those records are returned.
The insert queries are stored in insert_books.sql under the resources/db_queries directory.
The actual test method is very straight-forward.

    @Test
    public void getBooks_ShouldReturnAListOfBooks() throws JSONException {

        //Given
        String expectedResponse = readFile(GET_BOOKS_RESPONSE);

        //When
        ResponseEntity<String> actualResponse = TestApiHelper.getForEntity(applicationPort, GET_BOOKS);

        //Then
        assertEquals(expectedResponse, actualResponse.getBody(), JSONCompareMode.STRICT);
    }

Hope I could be of some help to you. You may view the full source code here on GitHub