Getting “Error: Resolution method is overspecified”? in beforeEach and afterEach - node.js

When I use done in beforeEach or afterEach I get this error “Error: Resolution method is overspecified” and the test fails.
But now if remove the done() all my tests pass but the terminal hangs without exiting the test script.
I am using knex.js as a query builder.
Is there a solution to this problem?
beforeEach(async (done) => {
await db.migrate.rollback(migrationConfig);
await db.migrate.latest(migrationConfig);
await db.seed.run(seedConfig);
done();
});
// cleaning db before running tests
afterEach(async (done) => {
await db.migrate.rollback(migrationConfig);
done();
});
describe("POST /user/login", () => {
it("should return a jwt after loging in user", (done) => {
chai
.request(server)
.post("/user/login")
.send({
email: "saaransh#test.com",
password: "test123",
})
.end((err, res) => {
res.should.have.status(200);
res.should.be.json;
res.body.should.have.property("token");
done();
});
});
});

If you are using async handler functions, then you should not give it parameter done. Promise returned by async function will tell Mocha when executing the function is ready.
beforeEach(async () => {
await db.migrate.rollback(migrationConfig);
await db.migrate.latest(migrationConfig);
await db.seed.run(seedConfig);
});
// cleaning db before running tests
afterEach(async () => {
await db.migrate.rollback(migrationConfig);
});

Related

sinon.stub isn't working in my api integration tests

i'm doing some integration tests in my API with mocha, chai, sinon and chai-http.
I made the tests for my post route and works fine, but, when I tried to do the same with my get route, the stub isn't workig. The code is bellow.
describe('Commentary API Test', () => {
describe('POST commentary', () => {
before(() => {
sinon.stub(CommentaryModel.prototype, 'add').resolves(newCommentaryResponse as any);
});
after(() => {
(CommentaryModel.prototype.add as SinonStub).restore();
});
it('should return status 201 and a new commentary json', async () => {
const response = await chai.request(app).post('/commentary').send(newCommentaryPayload)
expect(response).to.have.status(201);
expect(response.body).to.be.deep.equal(newCommentaryResponse);
});
it('should return error 400 with incorrect payload and a message', async () => {
const response = await chai.request(app).post('/commentary').send(newCommentaryPayload.pokemonName);
expect(response).to.have.status(400);
expect(response.body).to.be.deep.equal({"message":"All fields must be correctly filled"});
});
});
describe("GET commentaries", () => {
before(() => {
sinon.stub(CommentaryModel.prototype, 'get').resolves(1 as any);
});
after(() => {
(CommentaryModel.prototype.get as SinonStub).restore();
});
})
it('should return status 200 and a array with commentaries', async () => {
const response = await chai.request(app).get('/commentary');
console.log(response.body)
expect(response).to.have.status(200);
expect(response.body).to.be.equal(commentaryArray);
});
});
I put the number 1 as response, but i still getting a array with the pokemon infos... any idea why this stub isn't working?
Change the stub values some times.

How to use async/await with chai test?

I have a chai test that works without async/await syntax, but crashes with it. How to fix it?
The error is:
error Error [ERR_SERVER_ALREADY_LISTEN]: Listen method has been called more than once without closing.
code: 'ERR_SERVER_ALREADY_LISTEN'
Here is the same test with a working classic syntax and a non-working async/await syntax:
chai.use(chaiHttp);
const api = chai.request(server).keepOpen();
// async/await => doesn't work
describe("GET /user/:id", () => {
it("return user information", async (done) => {
const res = await api
.get("/user/123")
.set("Cookie", "_id=567;locale=en");
chai.expect(res.status).to.equal(200);
done();
});
});
// classic syntax => works
describe("GET /user/:id", () => {
it("return user information", () => {
api
.get("/user/123")
.set("Cookie", "_id=567;locale=en")
.end(function (err, res) {
chai.expect(res).to.have.status(200);
});
});
});

How to run two functions in mocha test sequentially

I have two describe blocks in my mocha-chai test, one for testing a POST API and another for a GET API. There is a dependency like the function for the GET API in turn calls the function for the POST API at first.
However, when I call both the functions one after another, both of them start simultaneously and thus failing.
The code looks like below :
var server;
var mongodb;
before(function (done) {
server = require('../../../app.js'); // same as "node app.js"
done();
})
after(function (done) {
server.close();
})
function this_is_post_call() {
describe('POST call', ()=> {
it('Creating project', (done) => {
chai.request(server)
.post('/create/myproject')
.send()
.end((err, res) => {
expect(res.statusCode).to.equal(200);
done();
});
});
});
}
function this_is_get_call() {
this_is_post_call();
describe('GET call', ()=> {
it('Reading project', (done) => {
chai.request(server)
.get('/read/myproject')
.send()
.end((err, res) => {
expect(res.statusCode).to.equal(200);
done();
});
});
}
this_is_post_call();
this_is_get_call();
Basically when I run this the standalone this_is_post_call() and the one inside this_is_get_call() , gets called simultaneously and it is failing as it tries to create same project twice.
What is the efficient way to call them sequentially so that they don't start until the previous one finishes.
Thanks.
something like this might work (not completely sure about the chai.request part)
var server;
var mongodb;
describe('server', () => {
before(function (done) {
server = require('../../../app.js'); // same as "node app.js"
done();
})
after(function (done) {
server.close();
})
beforeEach(() => {
// find a way to clear the database
// using mongodb variable maybe
})
describe('when you make a post', () => {
var postResult
beforeEach((done) => {
chai.request(server)
.post('/create/myproject')
.send()
.end((err, res) => {
var postResult = res
done();
});
})
})
it('should respond with OK', () => {
expect(postResult.statusCode).to.equal(200);
})
it('should let you make make a get', () => {
chai.request(server)
.get('/read/myproject')
.end((err, res) => {
expect(err).to.be.null;
expect(res.statusCode).to.equal(200);
done();
});
})
})
something like this might work too if you don't have a way to clear the database
var server;
var mongodb;
describe('server', () => {
before(function (done) {
server = require('../../../app.js'); // same as "node app.js"
done();
})
after(function (done) {
server.close();
})
it('should let you post and then get', () => {
var postResult
beforeEach((done) => {
chai.request(server)
.post('/create/myproject')
.send()
.end((err, res) => {
expect(postResult.statusCode).to.equal(200);
chai.request(server) // not sure if this is the correct chai.request format
.get('/read/myproject')
.end((err, res) => {
expect(err).to.be.null;
expect(res.statusCode).to.equal(200);
done();
});
});
})
})
})

Multiple before() or beforEach() in mocha

I need to do multiple async calls in before() hook in mocha. I need to delete a user, then signup , verify email and finally login to get token to authenticate all other test cases. Here is my code snippet :
const userInfo = {
"password": "pass123",
"email": "test#email.com",
};
var token = '' , userId = '';
before((done) => {
// Delete the user if already exists
User.remove({
email: userInfo.email
}).then((res) => {
// console.log(res.result);
})
.end(done);
done();
});
before((done) => {
request(app)
.post('/api/users')
.send(userInfo)
.expect(200)
.expect((res) => {
})
.end(done);
});
before((done) => {
User.findOne({
email: userInfo.email
}).then((res) => {
userId = res._id;
request(app)
.post('/api/users/verify-email')
.send({'token' : userId})
.expect(200)
.expect((res) => {
})
.end(done);
})
.end(done);
done();
});
Here these calls are not executing in sequence. I need to fetch userId before verifying the email, but I am getting below error:
POST /api/users/verify-email 401 4.082 ms - 45
1) "before all" hook
First of all, yes, mocha allows multiple before hooks and guarantees that they are called in the right order. To make sure of this you could run this snippet.
'use strict';
const results = [];
const assert = require('assert');
before(done => {
setTimeout(() => {
console.log(`First 'before'`);
results.push(1);
done(); //Will be called last
}, 1000)
});
before(done => {
setTimeout(() => {
console.log(`Second 'before'`);
results.push(2); //Will be called second
done();
}, 300)
});
before(done => {
setTimeout(() => {
console.log(`Third 'before'`);
results.push(3); //Will be called first
done();
}, 100)
});
describe('Before hooks order', () => {
it('should before hooks sequentially', () => {
//Check if the hooks were called in the right order anyway
assert.deepEqual(results, [1, 2, 3]);
});
});
//Output is:
// First 'before'
// Second 'before'
// Third 'before'
But to make this happen you need to call done() only when all the async operations are done to let mocha know that the hook is completed and it should run the next one.
Also there is a rule that any Node.js callback must be called only once. So here are a couple of fixes:
before((done) => {
// Delete the user if already exists
User
.remove({
email: userInfo.email
})
.then((res) => {
// console.log(res.result);
})
.end(done);
//Do not call done here() because User.remove have only started
//We need to wait until it finishes. Done will be called in .end method
// done();
});
before((done) => {
//All good here
request(app)
.post('/api/users')
.send(userInfo)
.expect(200)
.expect((res) => {
})
.end(done);
});
before((done) => {
User.findOne({
email: userInfo.email
}).then((res) => {
userId = res._id;
//You need a return statement here so the outer promise waits
//Until the internal call finishes
return request(app)
.post('/api/users/verify-email')
.send({'token': userId})
.expect(200)
.expect((res) => {
});
//We must not call callback multiple times, so remove this.
// .end(done);
})
//Now this 'end' will happen only after both calls finish
.end(done);
//Remove this please, for the same reason as with the first 'before'
// done();
});
Please check it out. I'm not able to run your code (don't have your api), so please let me know of any problems.

500 equals 400 passes in a mocha test?

Why does the following test pass?
"use strict";
const
path = require('path'),
Dexter = require('../src/Dexter.js'),
chai = require('chai'),
chaiHttp = require('chai-http'),
expect = chai.expect,
dexterServer = new Dexter(path.resolve(__dirname, 'test/data/sample.har'));
chai.use(chaiHttp);
describe('Rest API', () => {
before(() => {
dexterServer.startUp();
});
it('should\'ve started the server', function () {
chai.request('http://127.0.0.1:1121')
.get('/')
.end(function(err, response){
console.log(response.status);
expect(500).to.equal(400);// This passes? What?
done();
});
});
after(() => {
dexterServer.tearDown();
});
});
When I do a console.log of the response.status, I see a 200. But when I do
expect(response.status).to.equal(400);//response.status is an int
passes the test!
What am I doing wrong?
You forgot to pass done callback. it was treated as sync with 0 assumptions.
it('should\'ve started the server', function (done) {
chai.request('http://127.0.0.1:1121')
.get('/')
.end(function(err, response){
console.log(response.status);
expect(500).to.equal(400);// This passes? What?
done();
});
});
You have to pass done in it, before and after statement to maintain the asynchronous flow.
describe('Rest API', (done) => {
before(() => {
dexterServer.startUp();
});
it('should\'ve started the server', function (done) {
chai.request('http://127.0.0.1:1121')
.get('/')
.end(function(err, response){
console.log(response.status);
expect(500).to.equal(400);// This passes? What?
done();
});
});
after((done) => {
dexterServer.tearDown();
});
});
Mocha supports promises so you could use the fact that chai-http produces promises and just return the promise:
it('should\'ve started the server', function () {
// Return the promise.
return chai.request('http://127.0.0.1:1121')
.get('/')
// Use .then instead of .end.
.then(function(response){
console.log(response.status);
expect(500).to.equal(400);
});
});
If you need to do special processing of errors, you could have a .catch too. Otherwise, you can let Mocha handle any error as a failure.

Resources