I am using the MongoDB Java driver to perform some persistence in my application. The build for my application is managed via Maven and I'm looking for the best way to integrate a series of MongoDB-related unit tests into my Maven build process. I cannot assume that the user building the application has installed the MongoDB dameon as a service and therefore need to launch the daemon prior to the execution of the related unit tests.
My first thought was to store the binaries in the resources folder of the test directory (e.g., src/test/resources) and launch the daemon using Runtime.exec(). Is there an approach that's cleaner? I feel like Runtime.exec() is a quick and dirty way to get something working but not the most ideal...I need this to work on both linux and windows.
I've created a Maven plugin that wraps the flapdoodle.de 'embedded mongo' API:
It provides a start
goal that you can use to start any version of MongoDB you want (e.g. during pre-integration-test
), and a stop
goal that will stop MongoDB (e.g. during post-integration-test
).
MongoDB binaries are downloaded and stored in ~/.embedmongo
for future builds.
My team had this exact same problem but we could not find any clean way to solve it. We even went down a bad path of using the ant-run plugin to execute some Ant tasks (OS independent) which would start up the MongoDB daemon if necessary. We ended up scrapping the whole thing in favor for an AbstractMongoDbTest class which in it's @Before method, asserts MongoDB is running, and if not, fails the test with a very specific message prompting the user to start Mongo. It is not perfect but, unfortunately, if you are introducing an external dependency to your unit tests, they are not unit tests anymore, they are integration tests and it is not unreasonable to require people to have the dependency available.
Other options:
If all the developers are all on the same network, you could set up a dedicated MongoDB instance on a server and have the tests all point at it's hostname instead of localhost (the default).
You could also abstract all of the interactions with MongoDB behind repository-patterned interfaces with MongoDB implementations. This is probably a good idea anyway. This would allow your tests to either mock out the repo interfaces or create stubs of the services. This would keep your unit tests from becoming integration tests. It also has the advantage of if you ever decide to move away from MongoDB to maybe CouchDB or even a relational database like Oracle, your tests don't need to change, you simply need to create new implementations of your repo interfaces.
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