Question

I was looking for transaction support to rollback the changes while doing testing my app written in Spring+RESt+Mongo 2.4. But its not possible since we cant use transaction for mongodb. While searching about integration testing I found few links about embedMongo for doing integration testing. You can also do integration testing by having dedicated mongo db instance running somewhere. What special feature that embed mongo provides? I didn't find great documentation for it, Is it under Apache license?

Was it helpful?

Solution

I was looking for transaction support to rollback the changes while doing testing my app written in Spring+RESt+Mongo 2.4. But its not possible since we cant use transaction for mongodb.

Transactions aren't supported, but you do have a few alternative approaches for rolling back changes while testing:

  • create/reset data as needed during set up or tear down in your unit tests
  • seed your initial data set and start mongod with --syncdelay=0 during your testing so no new data is written to disk (Embedded MongoDB suggests this as a "snapshot" approach)

While searching about integration testing I found few links about embedMongo for doing integration testing. You can also do integration testing by having dedicated mongo db instance running somewhere. What special feature that embed mongo provides?

Embedded MongoDB is a wrapper around the standard MongoDB Server binaries intended to help with unit testing. The "special features" of the wrapper are just functions to start/stop MongoDB instances via your unit tests.

Also see the comments on: Embedded MongoDB when running integration tests.

I didn't find great documentation for it, Is it under Apache license?

The "Embedded MongoDB" source files on GitHub suggest Apache 2.0 license.

The MongoDB server binaries will use the standard MongoDB Server community license, which is AGPL v3.0.

OTHER TIPS

In your integration testing, you just need to use the @DirtiesContext annotation.

This example will reset the MongoDB database after each test method:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class OrderControllerIT {

This annotation can also be used with @DataMongoTest. This works very well using the flapdoodle Embedded Mongo.

I have used the following mechanism to simulate @Transactional tests

Created a simple class that simulates rollbacks by

  • saving a snapshot of the DB state before a test
  • restoring it after the test.

Or if all tests start off with the same DB state, then save the snapshot the very first time and just restore it before every other test.

Sample test helper

@Service
public class MongoTestHelper {
    @Autowired
    private MongoTemplate mongoTemplate;

    private Map<String, List<Document>> snapshot = null;

    public void createSnapshot() {
        this.snapshot = new HashMap<>();
        mongoTemplate.getCollectionNames().forEach(collectionName ->
            {
                List<Document> collectionDocs = new ArrayList<>();
                mongoTemplate.getCollection(collectionName).find(Document.class)
                    .forEach((Consumer<? super Document>) collectionDocs::add);
                snapshot.put(collectionName, collectionDocs);
            }
        );
    }

    public void restoreSnapshot() {
        snapshot.keySet().forEach(collectionName -> {
            mongoTemplate.dropCollection(collectionName);
            snapshot.get(collectionName).forEach(d ->
                mongoTemplate.insert(d, collectionName)
            );
        });
    }

    public boolean hasSnapshot() {
        return this.snapshot != null;
    }
}

Usage

In the setUp method AbstractIntTest class that is shared among all Integration tests I put:

public void setUp() { 
    if (mongoHelper.hasSnapshot()) {
        // if there is a saved snapshot just restore it
        mongoHelper.restoreSnapshot();
    } else {
        // this is the very first run: create the snapshot
        mongoHelper.createSnapshot();
    }
}

PS. You may extend the following approach to save/restore indexes and other DB related things.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top