What is mongoUnit?
mongoUnit is a data driven Integration testing framework for Spring Boot based applications that use MongoDB for persistence. The framework enables the developer to test the data access logic with relative ease.
mongoUnit follows close to the same principles and is modeled after DBUnit, so I’ll paraphrase its description as follows.
mongoUnit is a JUnit 5 extension targeted at MongoDB-driven projects (currently supporting implementations with Spring Boot) that, among other things, puts your database into a known state between test runs. This is an excellent way to avoid the myriad of problems that can occur when one test case corrupts the database and causes subsequent tests to fail or exacerbate the damage.
mongoUnit has the ability to export and import your database data to and from JSON datasets.
mongoUnit can also help you to verify that your database data match an expected set of values.
See mongoUnit in action
If you want to see a working (demo) project that uses mongoUnit, take a look at mongounit-demo2.
Here is an example of a test class from mongounit-demo2. Take a look for yourself as to how easy it is:
package org.mongounit.demo.dao.mongo;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mongounit.AssertMatchesDataset;
import org.mongounit.LocationType;
import org.mongounit.MongoUnit;
import org.mongounit.MongoUnitTest;
import org.mongounit.SeedWithDataset;
import org.mongounit.demo.dao.model.Address;
import org.mongounit.demo.dao.model.CreatePersonRequest;
import org.mongounit.demo.dao.model.Person;
import org.mongounit.demo.dao.model.UpdatePersonRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@MongoUnitTest(name = "personDaoService")
@DisplayName("MongoPersonDaoService with MongoUnit testing framework")
public class MongoPersonDaoServiceIT {
@Autowired
private MongoPersonDaoService mongoPersonDaoService;
@Test
@DisplayName("Create person on an empty database")
@AssertMatchesDataset
void createPerson() {
CreatePersonRequest request = CreatePersonRequest.builder()
.name("Bob The Builder")
.address(Address.builder().street("12 Builder St.").zipcode(12345).build())
.favColors(Arrays.asList("red", "green"))
.positionName("Builder")
.build();
mongoPersonDaoService.createPerson(request);
}
@Test
@DisplayName("Create person on a non-empty database")
@SeedWithDataset
@AssertMatchesDataset
void createPersonWithExistingData() {
CreatePersonRequest request = CreatePersonRequest.builder()
.name("Robert")
.address(Address.builder().street("13 Builder St.").zipcode(12345).build())
.favColors(Arrays.asList("blue", "white"))
.positionName("Builder")
.build();
mongoPersonDaoService.createPerson(request);
}
@Test
@DisplayName("Create person on a non-empty database with explicit seed")
@SeedWithDataset("onePersonToStart.json")
@AssertMatchesDataset("expected2People.json")
void createPersonWithExistingDataExplicitSeed() {
CreatePersonRequest request = CreatePersonRequest.builder()
.name("Robert")
.address(Address.builder().street("13 Builder St.").zipcode(12345).build())
.favColors(Arrays.asList("blue", "white"))
.positionName("Builder")
.build();
mongoPersonDaoService.createPerson(request);
}
@Test
@DisplayName("Create person on a non-empty database with classpath root datasets")
@SeedWithDataset(
value = "common/createPersonWithExistingData-seed.json",
locationType = LocationType.CLASSPATH_ROOT)
@AssertMatchesDataset(
value = "common/createPersonWithExistingData-expected.json",
locationType = LocationType.CLASSPATH_ROOT
)
void createPersonWithExistingDataWithPackageRelative() {
CreatePersonRequest request = CreatePersonRequest.builder()
.name("Robert")
.address(Address.builder().street("13 Builder St.").zipcode(12345).build())
.favColors(Arrays.asList("blue", "white"))
.positionName("Builder")
.build();
mongoPersonDaoService.createPerson(request);
}
@Test
@DisplayName("Update person")
@SeedWithDataset("createPersonWithExistingData-seed.json")
@AssertMatchesDataset
void updatePerson() {
UpdatePersonRequest updateRequest =
new UpdatePersonRequest(
"5db7545b7b615c739732c777",
"Builder",
"Robert",
Arrays.asList("red", "green"),
new Address("12 Builder St.", 12345));
mongoPersonDaoService.updatePerson(updateRequest);
// Any other API functions can be called here and asserted as usual
Person updatedPerson = mongoPersonDaoService.getPerson("5db7545b7b615c739732c777");
assertTrue(
updatedPerson.getCreated().compareTo(updatedPerson.getUpdated()) < 0,
"Updated data should be after created date");
}
@Test
@DisplayName("Update person - Manual MongoUnit Testing")
void updatePersonManualTest() {
// Seed with data
MongoUnit.seedWithDataset("createPersonWithExistingData-seed.json", this.getClass());
// Perform API action
UpdatePersonRequest updateRequest =
new UpdatePersonRequest(
"5db7545b7b615c739732c777",
"Builder",
"Robert",
Arrays.asList("red", "green"),
new Address("12 Builder St.", 12345));
mongoPersonDaoService.updatePerson(updateRequest);
// Any other API functions can be called here and asserted as usual
Person updatedPerson = mongoPersonDaoService.getPerson("5db7545b7b615c739732c777");
assertTrue(
updatedPerson.getCreated().compareTo(updatedPerson.getUpdated()) < 0,
"Updated data should be after created date");
// Assert database is in the expected state
MongoUnit.assertMatchesDataset("updatePerson-expected.json", this.getClass());
}
@Test
@DisplayName("Delete person")
@SeedWithDataset("createPersonWithExistingData-seed.json")
@AssertMatchesDataset
void deletePersonKeepCollections() {
mongoPersonDaoService.deletePerson("5db7545b7b615c739732c777");
}
}