What is a good in memory database for junit test?
Databases such as HSQLDB do not behave exactly like MySQL. The advantage of testing with HSQLDB is to flag some of the unintended errors in your code which might pass under MySQL. For example some invalid aggregate queries work under MySQL but not HSQLDB.
How to write in test case with in-memory-database?
You should initialize your Hibernate SessionFactory
with another hibernate config, that uses H2 in-memory database, example test-hibenate.properties
:
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.connection.url=jdbc:h2:mem:orm
javax.persistence.schema-generation.database.action=drop-and-create
Then in your tests you can use your DAO's just in regular way.
If you use plain JDBC, you can create connection to H2 in-memory database this way:
Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "", "");
And you will need H2 database dependency:
https://mvnrepository.com/artifact/com.h2database/h2
Configure specific in memory database for testing purpose in Spring
Spring profiles can be used for this. This would be a specific way:
Have environment specific properties files:
application.properties:
spring.profiles.active: dev
application-dev.properties
spring.jpa.database: MYSQL
spring.jpa.hibernate.ddl-auto: update
spring.datasource.url: jdbc:mysql://localhost:3306/dbname
spring.datasource.username: username
spring.datasource.password: password
application-test.properties
spring.jpa.database: HSQL
Have both MySQL and H2 drivers in pom.xml
, like this:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
Last but not the least, annotate Test classes with @ActiveProfiles("test")
.
Use in-memory db to write tests for Rest controllers
Assuming you annotate class with @SpringBootApplication
, which enables auto-configuration and you have H2
dependency on classpath(see below) Spring Boot
will see H2
in-memory database dependency and it will create javax.sql.DataSource
implementation. Default connection URL is jdbc:h2:mem:testdb
and the default username and password are: username: sa and password: empty.
application.properties file
spring.datasource.url=jdbc:h2:mem:tesdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.h2.console.enabled=true // if you need console
H2 Dependency
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency> // If you need h2 web console
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
You can gain access to h2 console for management http://localhost:8080/h2-console
How to create unit tests against non in-memory database such as MySQL in Play framework, with resetting to known state?
First, I would recommend you to use the same RDBMS for testing and production as it could avoid some hard-to-find bugs.
Concerning the need to clean your database between each test, you can use Ebean DdlGenerator
to generate scripts to create a clean database and JUnit's @Before
annotation to automatically execute these scripts before every test.
Using the DdlGenerator
can be done like this :
EbeanServer server = Ebean.getServer(serverName);
ServerConfig config = new ServerConfig();
DdlGenerator ddl = new DdlGenerator((SpiEbeanServer) server, new MySqlPlatform(), config);
This code can be placed in a base-class that you could make inherit your tests (or inside a custom Runner
that you can use with the @RunWith
annotation).
It will also allow you to easily automate the FakeApplication
creation, avoiding some boilerplate code.
Some links that can be helpful :
- http://blog.matthieuguillermin.fr/2012/03/unit-testing-tricks-for-play-2-0-and-ebean/
- https://gist.github.com/nboire/2819920
Unit Testing(Mocking) Databases, How To Verify Database Methods With Mocking?
Imagine the following... You have two cars, one is a real car, another is a fake (mock) car. Now you get into the real car and drive off. Why do you expect not to move? You didn't do anything with the fake car, so even if you told it "Do not move if I start driving", this doesn't change the fact that the real car WILL move when you drive off.
Same thing here, you created a fake DBConnection and a real one. The real one will do whatever the real one does. The fake one can be configured to do different stuff, like you did with Mockito.when(...). But that doesn't change the behavior of the real one.
Your test is effectively meaningless, because your only choice here is to get rid of the mock, because it doesn't serve any meaningful purpose. You do not test a mock. What for? That's like creating a fake car and testing that - it doesn't tell you anything about the real car. You do not need to test the fake car to find out that it will do X if you told it to do X in that test.
There are two ways you can test your DBConnection class:
a) You can connect it to a database and check that it does what it should. This would, of course, be an integration test and not a unit test anymore. In some cases you can use a in-memory database like HSQLDB to speed up this test. But at least in the end you can be reasonably sure that your code does what it is supposed to be doing.
b) IF and only IF DBConnection has some objects internally that do the actual talking to the database, you can, perhaps, mock those and then test DBConnection. Of course, this only moves your problem to another layer, because then you aren't sure that those objects work - you will only know that DBConnection works IF those objects work. While this is good to know, it does not answer the question if your db code will work in the end.
In the end, you can only test db connections completely by connecting to a db. Everything else is not a complete test.
Related Topics
Printing Message on Console Without Using Main() Method
How to Check If a String Starts with One of Several Prefixes
Why Do I Need a Functional Interface to Work with Lambdas
Differencebetween String and Stringbuffer in Java
Reverse Hashmap Keys and Values in Java
Create File with Given Size in Java
Is Executorservice (Specifically Threadpoolexecutor) Thread Safe
Java 8: How to Work with Exception Throwing Methods in Streams
How Does the Enhanced for Statement Work for Arrays, and How to Get an Iterator for an Array
How to Find the Index of an Element in an Int Array
Java: Bufferedimage to Byte Array and Back
What Do Curly Braces in Java Mean by Themselves
Java Inheritance - Calling Superclass Method