G33k, Programmes

How do I mock javax.sql.DataSource

This is the annoying question I have had to ask myself.

Integration tests are pretty slow. Even when they use a dedicated database like H2 or Derby, they are still accessing dark infrastructure software layers to read / edit / write / flush data.
I was wanting tests able to run in no time and still performing data manipulation.

Rather than trying to mock each Data Access layer (and I have got many of them), how can I simply mock responses from databases without having to do bespoke mocks engineering.

Actually DataSource interface (which is a really primitive interface) can be mocked if we simulate the right methods.
DataSource also has a lot of dependencies and axioms that won’t be called by your application … so don’t create mocks for them.
Otherwise you will spend weeks defining your tests strategy.

I have digged into the Java Database Connectivity interfaces to understand the main interactions between roles and I could create several mocks to allow the critical path of the data flow go without any error

You will need to mock : DataSource, PreparedStatement, ResultSet and Connection,

Now the question is : Do I have to prepare tables before the tests ?
Well to be honest, only one Map. You can register a mapping between SQL requests and results (we will call it registeredSQLServerMappings).

And you can verify the results of your call by making the mocks update a mutable list, let’s call it calledStatements.

Here is the gist : https://gist.github.com/libetl/48beff8234a7e034762fa23f6692cb86. Anyone can copy and the only pre-requisite to use is to have mockK in the classpath (and kotlin).

To use it in your test,
– have a BeforeEach to do
val dataSource = mockk<DataSource>().simulateDatabase()
– register some mappings like with that example :
registeredSQLServerMappings["SELECT ID, TICKET_NUMBER, FIRST_NAME, LAST_NAME FROM DOCUMENT"] = listOf(
mapOf("ID" to 1234, "TICKET_NUMBER" to "ABCD", "FIRST_NAME" to "John", "LAST_NAME" to "Doe")
).toResultSet()

– use that DataSource in your data layer bean.
– Congratulations, you can now use a mocked database in your unit tests and they run in less than one second each.

Leave a comment