I'm building a basic HTTP API and some actions like POST /users
create a new user record in the database.
I understand that I could mock these calls, but at some level I'm wondering if it's easier to let my Junit tests run against a real (test) database? Is this a bad practice? Should only integration tests run against a real DB?
I'm using flyway to maintain my test schema and maven for my build, so I can have it recreate the test DB with the proper schema on each build. But I'm also worried that I'd need some additional overhead to maintain/clean the state of the database between each test, and I'm not sure if there's a good way to do that.
Unit tests shouldn't depend on infrastructure There's no way to test this function without having a database connection available at the time of testing. If a new developer clones the project they will need to set up a database or else tests will fail.
The best solution is to virtualise and parallelise your isolated integration tests against a well-known data set. It runs more slowly, but you'll spend much less time setting this up correctly, fixing bugs that are due to bad mocking or bad emulation. Conclusion: Stop mocking your database.
In the context of applications using a database, integration tests usually require a database to be available and contain data that is convenient to the scenarios intended to be tested. One way to simulate a real world environment is to use Docker to encapsulate a database and some test data.
Unit tests are used to test single unit of code. This means that you write a unit test by writing something that tests a method only. If there are external dependencies then you mock them instead of actually calling and using those dependencies.
So, if you write code and it interacts with the real database, then it is not a unit test. Say, for some reason your call to db fails then unit test will also fail. Success or failure of your unit test should not be dependent on the external dependencies like db in your case. You have to assume that db call is successful and then hard code the data using some mocking framework(Mockito) and then test your method using that data.
As often, it depends.
On big projects with lots of JUnit tests, the overhead for the performance can be a point. Also the work time needed for the setup of the test data within the database as well as the needed concept for your tests not interfering with the test data of other tests while parallel execution of JUnit tests is a very big argument for only testing against a database if needed and otherwise mock it away.
On small projects this problems may be easier to handle so that you can always use a database but I personally wouldn't do that even on small projects.
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