0

I want to test an express app with mongoose. Therefor I am using AVA and Mockgoose.

Using the beforeEach hook of AVA I want to insert two documents into my database which I can then use in my tests.

The code looks like follows:

import test from 'ava';
import request from 'supertest';
import app from '../../../index';
import { connectDB, dropDB } from '../../utils/tests-helper';
import User from '../user.model';

const users = [
  new User({ username: 'test1', email: 'test1@test.de', password: '1234'}),
  new User({ username: 'test2', email: 'test2@test.de', password: '5678'}),
];

test.cb.beforeEach('Connect and add two users', t => {
  connectDB(t, () => {
    User.create(users, (err, user) => {
      if (err) t.fail('Unable to create users');
      t.end();
    });
  });
});

Then I have this test to make sure the code above worked:

test.serial('Should find the initially added users', async t => {
  t.plan(2);

  const firstUser = await User.findOne({ username: 'test1' }).exec();
  t.is(firstUser.username, 'test1');

  const secondUser = await User.findOne({ username: 'test2' }).exec();
  t.is(secondUser.username, 'test2');
});

This test also succeeds and works fine. After this test I have another test:

test.serial('Should return a 200 status when user loggs in', async t => {
  t.plan(1);

  //just for debugging
  User.findOne({email: 'test1@test.de'}, function(err, user) {
    console.log(user); //returns null
  });

  //just for debugging
  User.find({}, function(err, user) {
    console.log(user); //returns []
  });

  const res = await request(app)
    .post('/api/users/authenticate')
    .send({email: 'test1@test.de', password: '1234'});
  t.is(res.status, 200);
});

When I switch the order of the tests it's still working for the first one and failing for the second one. So for the first test my data does exist and for the second test it doesn't. Why is that? Why does it work in the first test?

It's working if I change the afterEach hook to an after hook, but I think this is not the way it should be? I think the database should be reset after each test and not after all tests.

Seems like the beforeEach hook only creates my users for the first time it's called and then doesn't work anymore..

This here are my DB helpers:

import mongoose from 'mongoose';
import mockgoose from 'mockgoose';
import config from '../../config/main';

function createMongooseConnection() {
  return new Promise((resolve, reject) => {
    mongoose.createConnection(config.mongoTestURL, err => {
      if (err) return reject('Unable to connect to test database');
      return resolve();
    });
  });
}

export function connectDB() {
  return mockgoose(mongoose)
    .then(createMongooseConnection);
}

export function dropDB() {
  return new Promise((resolve, reject) => {
    mockgoose.reset(err => {
      if (err) return reject('Unable to reset test database');
      return resolve();
    });
  });
}
Sindre Sorhus
  • 62,972
  • 39
  • 168
  • 232
user2030592
  • 317
  • 2
  • 12
  • I assume your `afterEach` hook drops the database, though you haven't shown it. – Mark Wubben Feb 02 '17 at 10:59
  • Wow these comments post more easily than I thought… anyway, on to my second point, any chance Mongoose won't create records for the same `User` instance more than once? Since you're reusing the instances in the `beforeEach`. – Mark Wubben Feb 02 '17 at 11:00
  • thanks for the comment! so if mongoose won't create the records more than once a simple fix would be to move the users constant into the beforeEach hook, right? I just tried that and it doesn't change anything. – user2030592 Feb 06 '17 at 11:48
  • Hmm. Perhaps you need to add the `.serial` modifier to the `beforeEach` and `afterEach` calls? Though I'm under the impression that those run serially anyway if all you have are serial tests. – Mark Wubben Feb 07 '17 at 13:34

0 Answers0