-
Notifications
You must be signed in to change notification settings - Fork 1.4k
MongoDB testing recipe #1357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MongoDB testing recipe #1357
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking the effort to share this knowledge. I have a bunch of comments, hope you don't mind 😊 😄 The upshot is that there are some AVA features I think this can take advantage of.
Should the test.always.after()
teardown be documented? You mention it here: #807 (comment).
I tried to find the source for mongomem
but https://www.npmjs.com/package/mongomem doesn't have a link?
@@ -0,0 +1,86 @@ | |||
# Setting up Ava for Isolated MongoDB Integration Tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's AVA
in all-caps 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙈 apologies!
|
||
## Using MongoMem | ||
In your test file, import the module and run the server. | ||
*Make sure to run the server at the start of your file, outside of any test cases.* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intend for this to be on its own line? Cause GitHub renders it right after "run the server."
*Make sure to run the server at the start of your file, outside of any test cases.* | ||
|
||
```javascript | ||
import { MongoDBServer } from 'mongomem'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add the import test from "ava"
line as well.
let hasStarted = MongoDBServer.start(); | ||
|
||
// ES6 promise syntax | ||
test('some feature - es6', t => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're pretty vocal in advocating async
with AVA. I don't think we should include this example.
|
||
```javascript | ||
import { MongoDBServer } from 'mongomem'; | ||
let hasStarted = MongoDBServer.start(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may work even nicer with before
:
test.before(async () => {
await MongoDBServer.start()
})
Now tests don't have to await hasStarted
.
This should also work but might not be as obvious:
test.before(() => MongoDBServer.start())
test('my mongoose model integration test', async t => { | ||
await hasStarted; | ||
const odm = new mongoose.Mongoose(); | ||
odm.connect(await MongoDBServer.getConnectionString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should odm.connect()
be awaited?
|
||
test('my mongoose model integration test', async t => { | ||
await hasStarted; | ||
const odm = new mongoose.Mongoose(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is db
a more common name for this variable?
Object.keys(mongoose.models).forEach(name => { | ||
let model = mongoose.models[name]; | ||
odm.model(name, model.schema); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a modelNames()
function. I think this might be better:
for (const name of mongoose.modelNames()) {
odm.model(name, mongoose.model(name))
}
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. | ||
|
||
*You will need to re-attach the old models from the global mongoose to the new one as it does not carry this information over.* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps:
You will have to manually copy models from the global instance to your new instance.
|
||
// Now you can test with Mongoose using the 'odm' variable... | ||
}); | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps all this is better done in a beforeEach
:
test.beforeEach(async t => {
const db = new mongoose.Mongoose()
await db.connect(await MongoDBServer.getConnectionString())
for (const name of mongoose.modelNames()) {
db.model(name, mongoose.model(name))
}
t.context.db = db
})
test('my mongoose model integration test', async t => {
const {db} = t.context
// do something…
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with all of your comments. This was written in haste during my lunch hour so thanks for looking over it so thoroughly!
A big thanks for dropping the const {db} = t.context
knowledge-bomb on me. Didn't realise I could destructure an object inline like that. It's not so different to the import syntax but it just never occurred to me! 🥇
npm is now referenced to the source code and readme :) |
… schema, not the model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sweet. Almost good to go.
# Setting up AVA for Isolated MongoDB Integration Tests | ||
|
||
This recipe outlines how to run disposable MongoDB databases in your AVA tests with per-test isolation. | ||
This uses `mongomem` and is available on [npm](https://www.npmjs.com/package/mongomem). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"which is available"
This is normally cleaned up by your operating system but it is good practise to do it manually to avoid OS-specific issues. | ||
|
||
```javascript | ||
test.after.always('cleanup', async t => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look like it has to be async
?
|
||
test.beforeEach(async t => { | ||
const db = new mongoose.Mongoose(); | ||
await db.connect(await MongoDBServer.getConnectionString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too much indentation here.
|
||
test('my mongoose model integration test', async t => { | ||
const {db} = t.context; | ||
// do something… |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too much indentation here as well.
The "do something" comment is a bit flippant (my bad!). Perhaps something like // Now use the isolated DB instance in your test
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha, no worries. I'm not sure what has been going on with my grammar in this pull request! 😅
In terms of indentation, what do you normally use for AVA? 4 spaces?
I tend to stick to tab, so I'll need to change it for the next submission depending on your answer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go with the readme, which uses tabs (except for package.json
which uses two spaces because of npm).
const connectionString = await MongoDBServer.getConnectionString(); | ||
|
||
// connectionString === 'mongodb://localhost:27017/3411fd12-b5d6-4860-854c-5bbdb011cb93' | ||
// use connectionString to connect to the database with a client of your choice. See below for usage with Mongoose. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has tab indentation, unlike the other code samples. It looks a bit odd when the Markdown is rendered.
|
||
```javascript | ||
import mongoose from 'mongoose'; | ||
import { MongoDBServer } from 'mongomem' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency, this should end with a ;
😜
Does this seem ok now? Indentation on Github seems rather excessive to me, but my editor definitely reports a sensible number of tabs. |
Great! I'll leave this open for a day or so in case anybody else wants to chime in. |
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. | ||
|
||
This is normally cleaned up by your operating system but it is good practise to do it manually to avoid OS-specific issues. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid OS-specific issues
What kind of issues?
Looks good. I did some minor cleanup. This needs to be added to the Recipes section in the main readme: https://github.com/avajs/ava#recipes |
ping @CImrie :) |
Includes a recipe detailing how to run isolated MongoDB tests using an in-memory MongoDB server.
Includes 'extra' steps to run with Mongoose.
As request in #807 .