In episode 22 we how to seed a database with spring's @Sql annotation so lets extend it and find out how to test a domain with database interactions.
Detailed Video Notes
Getting started
For our exercise we have been given a user story to "Update an existing person's password" which will require us to create a Person table, POJO and a data access object. We will use spring's jdbcTemplate to interact with the database but it could be substituted by injecting mybatis or hibernate data access beans. Once those pieces are created we will put it together an integration test.
This process may vary depending what techniques and methodologies you are using such as TDD.
Project set up
[0:21]
Let's get started by creating a spring boot project from the starter web site selecting spring-boot-starter-jdbc
and spring-boot-starter-web
. We will then download and import the maven project into eclipse while adding derby as additional dependency in the pom.xml. Spring-boot recognizes derby is on the classpath and auto configures an embedded database which means you do not need to specify any connection URLs or driver class names (pretty neat). If you are wanting to dig into the specifics check out EmbeddedDatabaseConnection and EmbeddedDataSourceConfiguration.
Derby could be substituted with other databases such as oracle, mysql or another database by specifying properties in application.properties or application.yml.
Creating Person domain and DAO
[1:2]
Next lets create a Person
POJO and PersonDAO
. As we mentioned earlier the PersonDAO
will use JdbcTemplate
abstraction to access the database. We implemented a PersonRowMapper
that implements RowMapper
to map result set row to a Person object, a getPerson
and updatePassword
method.
Setting up the database
[1:25]
Once the foundation is created, we will want to write a test to validate that a person's password was updated. An important thing to mention is when running integration tests against a database is that is in a known state before each test to have consistent reproducible tests. To achieve this we will use spring's @Sql and @SqlGroup annotation.
We covered this in detail in episode 22 so at a high level using these annotations we create a person table, preload the entry of "Fred" and drop the table upon completion of the test all against our embedded database.
Writing the test
[1:50]
After the database and data is set up we are ready to write our unit test. Since we know we seeded the database with a person and their id equaling one, we will create a Person
object setting the id to 1 and the password to "wilma". In the event that we didn't know which person existed we could first queried the database to get a random person and followed the same steps.
Next calling the personDAO.updatePassword
and passing the Person
object we just created will execute an update statement which we can see by examining the logs.
Finally we can validate the update occured by calling personDAO.getPerson
.
Putting it all together
Testing interactions between a domain and a database can be challenging and spring has made it easy to set up, tear down and execute scripts against a database. It is important to find the balance between what an integration test can offer and interactions you can test with mocking frameworks such as mockito.
Thanks for joining in today's level up, have a great day!