Group Testing with MongoDB

My database of choice is MongoDB. I am writing a data-level API for an abstract implementation detail from client applications, that is, I essentially provide a single open interface (an object that acts as an IDL).

I test my logic when I enter TDD. Before each unit test, the @Before method is @Before to create a singleton database, after which, when the test completes, the @After method is @After to delete the database. This helps increase independence from unit tests.

In almost all unit tests, that is, when executing a contextual query, some kind of insertion logic is required, which must happen before hand. My open interface provides an insert method - however, it seems incorrect to use this method as the predecessor logic for each unit test.

Actually, I need some kind of mocking mechanism, but I didn’t have much experience in mocking frameworks, and it seems that Google is not returning anything from the mocking frame that can be used with MongoDB.

What do others do in these situations? That is, how are people unit test code that interacts with the database?

In addition, my open interface connects to the database defined in the external configuration file - it seems wrong to use this connection for my unit testing - again, a situation that would benefit from some kind of ridicule?

+46
java unit-testing junit mongodb morphia
Sep 14 '11 at 9:18
source share
3 answers

Technically, tests that talk to a database (nosql or otherwise) are not unit tests , because tests test interactions with an external system, and not just test an isolated code unit. However, tests that speak to the database are often extremely useful and often fast enough to work with other unit tests.

Usually I have a service interface (e.g. UserService) that encapsulates all the logic of working with the database. Code that uses UserService can use a modified version of UserService and is easily tested.

When testing an implementation of a Service that is negotiating with Mongo (e.g. MongoUserService), the easiest way is to write some Java code that will start / stop the mongo process on the local machine and connect your MongoUserService to this, see this question for some notes .

You can try to mock the functionality of the database when testing MongoUserService, but as a rule, this is too error-prone and does not test what you really want to test, but this is interaction with a real database. Therefore, when writing tests for MongoUserService, you configure the state of the database for each test. See DbUnit for an example structure for this with a database.

+41
Nov 25 '11 at 6:13
source share

As sbridges wrote in this post, it is a bad idea not to have a dedicated service (sometimes also known as a repository or DAO) that abstracts access to data from logic. You can then test the logic by providing a DAO layout.

Another approach I'm doing is to create a mock of a Mongo object (like PowerMockito) and then return the corresponding results. This is because you do not need to check whether the database works in unit tests, but in more detail you should check whether the correct request was sent to the database.

 Mongo mongo = PowerMockito.mock(Mongo.class); DB db = PowerMockito.mock(DB.class); DBCollection dbCollection = PowerMockito.mock(DBCollection.class); PowerMockito.when(mongo.getDB("foo")).thenReturn(db); PowerMockito.when(db.getCollection("bar")).thenReturn(dbCollection); MyService svc = new MyService(mongo); // Use some kind of dependency injection svc.getObjectById(1); PowerMockito.verify(dbCollection).findOne(new BasicDBObject("_id", 1)); 

This will also be an option. Of course, creating mocks and returning the corresponding objects is simply encoded as an example above.

+22
Nov 25 '11 at 7:29
source share

I wrote an implementation of stub MongoDB in Java: mongo-java-server

By default, internal memory is used, which can be easily used in Unit and Integration tests.

Example

 MongoServer server = new MongoServer(new MemoryBackend()); // bind on a random local port InetSocketAddress serverAddress = server.bind(); MongoClient client = new MongoClient(new ServerAddress(serverAddress)); DBCollection coll = client.getDB("testdb").getCollection("testcoll"); // creates the database and collection in memory and inserts the object coll.insert(new BasicDBObject("key", "value")); assertEquals(1, collection.count()); assertEquals("value", collection.findOne().get("key")); client.close(); server.shutdownNow(); 
+14
Feb 20 '13 at 17:29
source share



All Articles