Open tamlyn opened 9 years ago
Good question.
When we've done MongoDB-based apps we create the db
in the first test (usually named _setup.js
or _db.js
(the underscore in the file name is the important bit because the test runner opens files alphabetically).
Then drop the database with a db.dropDatabase()
call at the end of our test suite (usually in a file called z_teardown.js
again for alphabetical reasons).
see: http://docs.mongodb.org/manual/reference/command/dropDatabase/ Here's an example, but using ElasticSearch: https://github.com/dwyl/api/tree/master/test
Note: you may need to use node-mongodb-native run
command to create the DB. But Mongoose should auto-create the DB when a record is first inserted into Mongo: http://stackoverflow.com/questions/16459286/how-to-create-a-new-db-in-mongoose
We usually create methods specific to our project and export them as a module e.g:
your-project-name/test/_test_helpers.js
e.g: https://github.com/dwyl/api/blob/master/test/_test_helpers.js so we can include the module in any file while testing a single file/test.
Let us know if that answers your question. Thanks!
Thanks.
Actually by default Mocha runs files in whatever order the filesystem gives them which is essentially random. You have to specify the -S
flag to sort files. However a better solution is to use global before
and after
hooks and not worry about execution order.
You also gave me the idea of only deleting the database if it didn't exist in the first place. That way we can be sure not to delete anything important.
var mongoose = require('mongoose');
var fixtures = require('../../server/fixtures');
//should we delete the database after the test run?
var deleteAfterRun = false;
//run once before all tests
before(function (done) {
//test if database is populated
var User = mongoose.model('User');
User.count({})
.then(function (count) {
if (count === 0) {
//no content so safe to delete
deleteAfterRun = true;
//add test data
return fixtures.ensureTestData();
} else {
console.log('Test database already exists');
}
})
.then(function() {
done();
});
});
//run once after all tests
after(function (done) {
if (deleteAfterRun) {
console.log('Deleting test database');
mongoose.connection.db.dropDatabase(done);
} else {
console.log('Not deleting test database because it already existed before run');
done();
}
});
@tamlyn Sweet! that's a much cleaner solution (for Mocha) We went Mocha > Lab > Tape > QUnit (our current preferred testing framework)
Hey guys, since 2 years, does something changed? I mean, now I also trying to test some of models and api in mongo/mongoose based app, so tests need to have running database. I wrote some helper module for tests which looks like
/*
Before running tests which requires database connection could be useful to
0) init db connection
1) ensure that we have connection
2) clean database
*/
const mongoose = require('mongoose')
require('dotenv').config()
require('../initdb')() // here actual connection happens, also here some reconnect logic for app, so module used by app
module.exports = {
ensureConnection() {
return new Promise((resolve) => {
if (mongoose.connection.db) {
return resolve(mongoose.connection.db)
}
mongoose.connection.on('connected', () =>
resolve(mongoose.connection.db)
)
})
},
cleanDatabase() {
return mongoose.connection.db.dropDatabase()
}
}
Generally, in tests, I want to drop db in first before
block for suite (main describe in test file I mean) and in last after
block. What I concerned about: is there some guaranties that test files never be run by mocha in parallel?
How do you test your code in 2017?
In 2018, acceptance tests (e.g. with jest
and jest-puppeteer
) can run meteor with meteor test --full-app --driver-package tmeasday:acceptance-test-driver --settings test-settings.json --port 1234
then hit http://localhost:1234
to drive their tests. This starts meteor in a fresh state each time with Meteor.isTest === true
so your fixtures can do their thing.
Unit tests should use in memory collection mocks so that they are isolated from one another.
Integration tests that involve the database probably want to test the production techniques anyway.
In order to have repeatable tests it seems a good idea to have a test database populated with known data against which to write the tests. Populating this database is straightforward and resetting it could be as simple as dropping it at the end of the test. But adding an automated
drop database
to my test scripts seems like a very bad idea since a config error could easily result in dropping a production database. Any suggestions? I'm using MongoDB and Mocha/Karma/Protractor.