Skip to content

Add docs for endpoint testing with mongoose #1420

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 15 commits into from
Sep 2, 2017
37 changes: 15 additions & 22 deletions docs/recipes/endpoint-testing-with-mongoose.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ This recipe shows you how to test your endpoints with AVA and Mongoose, assuming
This recipe uses the following libraries:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should mention here that the recipe assumes you have an Express server

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


1. [MongoDB memory server](https://github.com/nodkz/mongodb-memory-server) (A MongoDB in-memory Server)
2. [Babel Polyfill](https://babeljs.io/docs/usage/polyfill/) (required for MongoDB memory server)
3. [Supertest](https://github.com/visionmedia/supertest) (An endpoint testing library)
4. [Mongoose](http://mongoosejs.com)
2. [Supertest](https://github.com/visionmedia/supertest) (An endpoint testing library)
3. [Mongoose](http://mongoosejs.com)

Install the first three libraries by running the following code:
Install the first two libraries by running the following code:

```console
$ npm install --save-dev mongodb-memory-server babel-polyfill supertest
$ npm install --save-dev mongodb-memory-server supertest
```

You should have Mongoose installed already. If not, run the following code to install it:
Expand All @@ -25,18 +24,6 @@ You should have Mongoose installed already. If not, run the following code to in
$ npm install mongoose
```

## Setting up AVA

Since MongoDB Memory server requires Babel polyfill to work, the easiest way to set up AVA is through the `ava` key in your `package.json` file.

```json
"ava": {
"require": [
"babel-polyfill"
]
},
```

## Your test file

First, include the libraries you need.
Expand Down Expand Up @@ -77,8 +64,6 @@ test.before(async t => mongoose.connect(await mongod.getConnectionString(), { us

When you run your first test, MongoDB downloads the latest MongoDB Binaries. It may take a minute. (The download is ~70mb).

Note: Since we're using async/await, you need Node v7.6 and above.

**Add fixtures for each test**

You'll want to populate your database with dummy data. Here's an example:
Expand All @@ -104,12 +89,10 @@ test.afterEach.always(async t => await User.remove())

Use Supertest to fire a request for your endpoint. Then, do the rest with AVA normally.

Note: Make sure your tests run serially with `test.serial`.

```js
// First test
// Note: tests must be serial tests.
// It is NOT RECOMMENDED to run parallel tests within an AVA test file when using Mongoose
// It is NOT RECOMMENDED to run parallel tests within an AVA test file when using Mongoose (see why below)
test.serial('litmus get user', async t => {
const { app } = t.context
const res = await request(app)
Expand Down Expand Up @@ -156,3 +139,13 @@ And you're done!
You may choose to abstract code for `test.before`, `test.beforeEach`, `test.afterEach.always` and `test.after.always` into a separate file.

To see a demo of this configuration file, look at https://github.com/zellwk/ava-mdb-test

## Why `test.serial` instead of `test`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use a new database for each test? That's how we run tests with agenda and we don't have any issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you use mongoose, you interact with the database through Mongoose. Since there can only be one Mongoose instance (and that Mongoose instance must always point to the same database), we cant access multiple databases even if we create them.

Do I make sense?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah! I understood @nodkz's explanation (above) wrongly. Although you can create multiple connections with Mongoose, you need to create multiple models. Let me switch the explanation as soon as I find some time to.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See User and UserOnServer2 models constructed on one schema with different connections in the following example:
https://github.com/nodkz/mongodb-memory-server#several-mongoose-connections-simultaneously

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OmgImAlexis updated with a slightly better explanation. Do I make sense in this new one?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does make sense but since ava is meant to be run in parallel it'd be better to explain how to set it up by default instead of expecting tests to run in serial.

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 fully understand that AVA runs tests in parallel, and your desire to set it up by default. I would love to do that too.

However, based on @nodkz's explanation, and my personal research over the past month, I strongly believe endpoint testing with Mongoose and AVA is an exception where serial tests would be preferred.

The setup for parallel tests changes how a person would create their schemas, and thus their app, too much for the additional benefit of running tests in parallel within each file. Besides, if you create multiple AVA test files, each test file still runs in parallel to other files, which shouldn't slow down testing too much.

I'll be glad to change the docs if you could show me a good way to run endpoint testing in parallel with Mongoose and Supertest.


AVA Test cases in a file uses the same Mongoose module (even when they're ran in parallel).

Since you need to use the same Mongoose module, you need to make sure each test fixture is completely cleared (with `test.after.always`) before beginning the next test. Otherwise, your database would be polluted data from the previous test.

The easiest way to make sure your databases remain clean across every test is to test serially, cleaning up after each test. Hence the use of `test.serial`.

There's a hard way (where you modify Mongoose and your models) that makes your code much more complex. If you want to try the hard way, check out the conversation in [this PR](https://github.com/avajs/ava/pull/1420)