Skip to content

Commit 970872c

Browse files
CImriesindresorhus
authored andcommitted
MongoDB testing recipe (#1357)
1 parent 1d04153 commit 970872c

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Isolated MongoDB integration tests
2+
3+
This recipe outlines how to run disposable MongoDB databases in your AVA tests with per-test isolation. This uses `mongomem` which is available on [npm](https://www.npmjs.com/package/mongomem).
4+
5+
`mongomem` is a package that allows you to quickly run a temporary MongoDB server locally. It uses temporary file storage which is destroyed when the server stops.
6+
7+
8+
## Install MongoDB in-memory Server (MongoMem)
9+
10+
In the root directory of your application, run:
11+
12+
```console
13+
$ npm install --save-dev mongomem
14+
```
15+
16+
17+
## Using MongoMem
18+
19+
In your test file, import the module, and run the server.
20+
21+
**Make sure to run the server at the start of your file, outside of any test cases.**
22+
23+
```js
24+
import test from 'ava';
25+
import {MongoDBServer} from 'mongomem';
26+
27+
test.before('start mongodb server', async t => {
28+
await MongoDBServer.start();
29+
})
30+
31+
test('some feature', async t => {
32+
const connectionString = await MongoDBServer.getConnectionString();
33+
34+
// connectionString === 'mongodb://localhost:27017/3411fd12-b5d6-4860-854c-5bbdb011cb93'
35+
// Use `connectionString` to connect to the database with a client of your choice. See below for usage with Mongoose.
36+
});
37+
```
38+
39+
40+
## Cleaning Up
41+
42+
After you have run your tests, you should include a `test.after.always()` method to clean up the MongoDB server. This will remove any temporary files the server used while running.
43+
44+
This is normally cleaned up by your operating system but it is good practise to do it manually to avoid OS-specific issues.
45+
46+
```js
47+
test.after.always('cleanup', t => {
48+
MongoDBServer.tearDown(); // This will clean up temporary file storage
49+
});
50+
```
51+
52+
53+
## Debugging
54+
55+
If the server does not seem to start, you can set the following option before you call `MongoDBServer.start()`:
56+
`MongoDBServer.debug = true;`
57+
58+
This will allow the MongoDB server to print connection or file permission errors when it's starting. It checks and picks an available port to run the server on, so errors are likely to be related to file permissions.
59+
60+
61+
## Extra: Setup and Use in Mongoose (MongoDB ODM)
62+
63+
Mongoose is a robust Object-Document-Mapper (ODM) for MongoDB. Refer to [Mongoose ODM v4.9.4](http://mongoosejs.com) for full guides and documentation to get started with Mongoose.
64+
65+
### Import Mongoose
66+
67+
```js
68+
// `myTestCase.test.js` - (your test case file!)
69+
import mongoose from 'mongoose';
70+
```
71+
72+
`mongoose` in this case is a single instance of the Mongoose ODM and is globally available. This is great for your app as it maintains a single access point to your database, but less great for isolated testing.
73+
74+
You should isolate Mongoose instances between your tests, so that the order of test execution is never depended on. This can be done with a little bit of work.
75+
76+
### Isolate Mongoose Instance
77+
78+
You can easily request a new instance of Mongoose. First, call `new mongoose.Mongoose()` to get the new instance, and then call `connect` with a database connection string provided by the `mongomem` package.
79+
80+
**You will have to manually copy models from the global instance to your new instance.**
81+
82+
```js
83+
import mongoose from 'mongoose';
84+
import {MongoDBServer} from 'mongomem';
85+
86+
test.before('start mongodb', async t => {
87+
await MongoDBServer.start();
88+
});
89+
90+
test.beforeEach(async t => {
91+
const db = new mongoose.Mongoose();
92+
await db.connect(await MongoDBServer.getConnectionString());
93+
94+
for (const name of mongoose.modelNames()) {
95+
db.model(name, mongoose.model(name).schema);
96+
}
97+
98+
t.context.db = db;
99+
});
100+
101+
test('my mongoose model integration test', async t => {
102+
const {db} = t.context;
103+
// Now use the isolated DB instance in your test
104+
});
105+
```

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,7 @@ It's the [Andromeda galaxy](https://simple.wikipedia.org/wiki/Andromeda_galaxy).
11631163
- [Debugging tests with Chrome DevTools](docs/recipes/debugging-with-chrome-devtools.md)
11641164
- [Debugging tests with WebStorm](docs/recipes/debugging-with-webstorm.md)
11651165
- [Precompiling source files with webpack](docs/recipes/precompiling-with-webpack.md)
1166+
- [Isolated MongoDB integration tests](docs/recipes/isolating-mongodb-integration-tests.md)
11661167

11671168
## Support
11681169

0 commit comments

Comments
 (0)