Reputation: 1835
I'm struggling to figure out the correct (i.e. not a hack) way to write these unit tests for my NodeJS app.
In server.js, I connect mongoose to the DB running on localhost:27017. When I run my mocha tests, I would like to connect to a different mongoDB instance running on localhost:37017, so that I am not running my tests against a live database. When I require mongoose in test.js and try to connect, mongoose throws an error, saying "Trying to open unclosed connection."
I have tried closing the current connection in test.js, however it doesn't work for some reason.
My question is: What is the proper way to connect to a test DB in one file, but continue letting server.js connect to the live DB?
My code is below:
// test.js
var app = require('../lib/server') // This connects mongoose to a database
var assert = require('assert');
var httpstatus = require('http-status');
var superagent = require('superagent');
// Connect to mongoose
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:37017/testDB'); // THIS THROWS ERROR because server.js is connecting to localhost:27017/liveDB
// Models we will be testing
var thing = require('../models/thing.js');
describe('Thing', function() {
before(function() {
// Clear the database here
}
beforeEach(function() {
// Insert, modify, set up records here
}
it('saves the thing to the database', function() {
// Save and query a thing here (to the test DB)
});
});
Upvotes: 1
Views: 1363
Reputation: 49182
npm i env-cmd --save // install this package
create config directory in the root of the project and create dev.env and test.env files in the config folder.
in test.env file, configure your test environment like this:
PORT=4000
MONGODB_URL=mongodb://127.0.0.1:27017/dbTestName
then in the package.json, load the settings of test.env into the test environment.
"test": "env-cmd -f ./config/test.env jest --watchAll --runInBand"
here we required the module and then loaded the test.env settings here.
env-cmd package will add all the settings from the .env files into process.env object depending on your environment. when you run run npm test
, your app will use the settings inside the test.env.
so in your application this is how you should use the MONGODB_URL to connect mongoose.
mongoose
.connect(process.env.MONGODB_URL, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false
})
.catch(err => {
console.log(err.message);
process.exit(1);
})
.then(() => {
console.log("connected to mongodb");
});
you will use settings inside the dev.env for your dev environment. Now you need to tweak the dev script inside the package.json
"dev": "env-cmd -f ./config/dev.env node src/index.js",
now when you run
npm run dev
your app load the settings from the dev.env
Upvotes: 0
Reputation: 203231
You could try this (although it's a hack):
// Connect to mongoose
var mongoose = require('mongoose');
before(function(done) {
mongoose.disconnect(function() {
mongoose.connect('mongodb://localhost:37017/testDB');
done();
});
});
// Models we will be testing (see text)
var thing = require('../models/thing.js');
...
describe(...)
It might be necessary to load your model inside the disconnect
handler as well, as it may "attach" to the original connection otherwise.
Again, this is still quite a hack, and I would suggest moving the configuration of your database to an external configuration file of some sorts, or use an environment variable, which could be relatively easy to implement:
// server.js
mongoose.connect(process.env.MONGO_URL || 'mongodb://localhost:27017/prodDB')
// test.js
process.env.MONGO_URL = 'mongodb://localhost:37017/testDB'
var app = require('../lib/server');
Upvotes: 1