Skip to content

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

Merged
merged 12 commits into from
May 6, 2017
Merged

MongoDB testing recipe #1357

merged 12 commits into from
May 6, 2017

Conversation

CImrie
Copy link
Contributor

@CImrie CImrie commented Apr 13, 2017

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 .

Copy link
Member

@novemberborn novemberborn left a 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
Copy link
Member

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 😄

Copy link
Contributor Author

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.*
Copy link
Member

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';
Copy link
Member

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 => {
Copy link
Member

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();
Copy link
Member

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());
Copy link
Member

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();
Copy link
Member

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);
});
Copy link
Member

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.*
Copy link
Member

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...
});
```
Copy link
Member

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…
})

Copy link
Contributor Author

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! 🥇

@CImrie
Copy link
Contributor Author

CImrie commented Apr 13, 2017

npm is now referenced to the source code and readme :)

Copy link
Member

@novemberborn novemberborn left a 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).
Copy link
Member

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 => {
Copy link
Member

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());
Copy link
Member

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…
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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.
Copy link
Member

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'
Copy link
Member

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 ; 😜

@CImrie
Copy link
Contributor Author

CImrie commented Apr 17, 2017

Does this seem ok now? Indentation on Github seems rather excessive to me, but my editor definitely reports a sensible number of tabs.

@novemberborn
Copy link
Member

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.
Copy link
Member

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?

@sindresorhus sindresorhus changed the title Mongodb testing recipe MongoDB testing recipe Apr 18, 2017
@sindresorhus
Copy link
Member

sindresorhus commented Apr 18, 2017

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

@sindresorhus
Copy link
Member

ping @CImrie :)

@sindresorhus sindresorhus merged commit 970872c into avajs:master May 6, 2017
@CImrie CImrie deleted the mongodb-testing-recipe branch May 6, 2017 14:07
sindresorhus added a commit that referenced this pull request May 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants