I use chai module to test code.
var CONFIG = require('./config');
var chai = require('chai');
var chaiHttp = require('chai-http');
var should = chai.should();
var server = CONFIG.apiPath;
chai.use(chaiHttp);
describe('TEST', function() {
it('getAllLandingPage completed',function(){
chai.request(server)
.get('getAllLandingPage')
.end(function(err, res){
res.should.have.status(200);
console.log('res: ', res) // not show
done();
});
});
});
I want console.log(res) to show result so I can to know function right or wrong
It seems you miss done in the callback function of it, try it as below
it('getAllLandingPage completed',function(done){
chai.request(server)
.get('getAllLandingPage')
.end(function(err, res){
if (err)
done(err);
else {
res.should.have.status(200);
console.log(res)
done();
}
});
});
Related
I´m writing some tests with chai and mocha and i am having some troubles.
For example, in the route that i paste down here, the LOGOUT calls the isLoggedIn middleware that checks if a user exists in the session.
For example, if a do this:
it('Logout', function(done) {
chai.request(baseURL)
.post('/logout')
.end(function(err, res) {
expect(err).to.be.null;
expect(res).to.have.status(204);
done();
});
});
the test faills cause i get a 401 status code. I am new on this test stuffs. I understand that i have to use sinon to get mi test pass, but i can´t get the solution.
This is my route:
'use strict';
const express = require('express');
const createError = require('http-errors');
const router = express.Router();
const bcrypt = require('bcrypt');
const User = require('../models/User');
const {isLoggedIn} = require('../helpers/middlewares');
router.post('/logout', isLoggedIn(), (req, res, next) => {
req.session.destroy();
return res.status(204).send();
});
This is the Middleware:
'use strict';
const createError = require('http-errors');
exports.isLoggedIn = () => (req, res, next) => {
if (req.session.user) {
next();
} else {
next(createError(401));
};
};
Thank you very much!!!
In your flow problem in that express middleware initialized during run express application and after becomes unavailable for stubbing. My solution is that would init stub before run express application.
test.spec.js:
const chai = require("chai"),
sinon = require("sinon"),
chaiHttp = require("chai-http"),
initServer = require("./initTestServer"),
isLoggedInMiddleware = require("./middleware");
chai.use(chaiHttp);
const { expect } = chai;
describe("Resource: /", function() {
before(function() {
sinon.stub(isLoggedInMiddleware, "isLoggedIn").callsFake(function() {
return (req, res, next) => {
next();
};
});
this.httpServer = initServer();
});
after(function() {
this.httpServer.close();
});
describe("#POST /login", function() {
beforeEach(function() {
this.sandbox = sinon.createSandbox();
});
afterEach(function() {
this.sandbox.restore();
});
it("- should login in system and return data", async function() {
return chai
.request(this.httpServer.server)
.post("/logout")
.end((err, res) => {
expect(err).to.be.null;
expect(res).to.have.status(204);
});
});
});
});
initTestServer.js:
const isLoggedInMiddleware = require("./middleware");
const initServer = () => {
const express = require("express");
const app = express();
app.post("/logout", isLoggedInMiddleware.isLoggedIn(), (req, res, next) => {
return res.status(204).send();
});
const server = require("http").createServer(app);
server.listen(3004);
const close = () => {
server.close();
global.console.log(`Close test server connection on ${process.env.PORT}`);
};
return { server, close };
};
module.exports = initServer;
Thank you #EduardS for then answer!!
I solved it in a similar way:
it('Logout', async function(done) {
sinon.stub(helpers, 'isLoggedIn')
helpers.isLoggedIn.callsFake((req, res, next) => {
return (req, res, next) => {
next();
};
})
app = require('../index')
chai.request(app)
.post('/api/auth/logout')
.end(function(err, res2) {
expect(res2).to.have.status(204);
helpers.isLoggedIn.restore()
})
done();
});
I'm using mocha, chai, and sinon to test some authenticated API routes. I'm using passport.authenticate() as middleware to authenticate the route:
const router = require('express').Router();
const passport = require('passport');
router.post('/route',
passport.authenticate('jwt', {session:false}),
function(req,res) {
return res.status(200);
});
module.exports = router;
Then, in my test suite, I am using sinon to stub out passport.authenticate calls:
const chai = require('chai');
const chaiHttp = require('chai-http');
const sinon = require('sinon');
const passport = require('passport');
const server = require('../../app');
const expect = chai.expect;
chai.use(chaiHttp);
describe('route', function() {
before(function(done) {
sinon.stub(passport, 'authenticate').callsFake(function(test, args) {
console.log('Auth stub');
});
console.log('stub registered');
passport.authenticate('jwt', {session:false});
done();
});
after(function(done) {
console.log('after hook');
passport.authenticate.restore();
done();
});
describe('POST /route', function() {
it('should post', function(done) {
console.log('starting test');
chai.request(server)
.post('/route')
.end(function(err,res) {
expect(res).to.have.status(200);
done();
});
});
});
});
Now, when I run the test suite, I see it print out the following:
route
stub registered
Auth stub
POST /route
starting test
1) should post
after hook
1 failing
1) route
POST /route
should post:
Uncaught AssertionError: expected { Object (_events, _eventsCount, ...) } to have status code 200 but got 401
From this, we can see that the after the stub is registered, I can call it in the test file and it is properly stubbed. But when passport.authenticate() is called in route.post(), it is the actual passport.authenticate() and sends a response with status 401 because I'm not authenticated.
Any thoughts on what's going on?
Your code calls passport.authenticate as soon as it runs, and it runs as soon as it is required.
Because you are requiring the code at the beginning of the test before the stub has been created your code ends up calling the real passport.authenticate.
In order for code like this to call the stub you must set up your stub before you require your code:
const chai = require('chai');
const chaiHttp = require('chai-http');
const sinon = require('sinon');
const passport = require('passport');
// const server = require('../../app'); <= don't require your code here...
const expect = chai.expect;
chai.use(chaiHttp);
describe('route', function () {
before(function (done) {
sinon.stub(passport, 'authenticate').callsFake(function (test, args) {
console.log('Auth stub');
});
console.log('stub registered');
passport.authenticate('jwt', { session: false });
done();
});
after(function (done) {
console.log('after hook');
passport.authenticate.restore();
done();
});
describe('POST /route', function () {
it('should post', function (done) {
console.log('starting test');
const server = require('../../app'); // <= require it AFTER creating the stub
chai.request(server)
.post('/route')
.end(function (err, res) {
expect(res).to.have.status(200);
done();
});
});
});
});
One small note related to sinon stubbing, I manage to have it working using this syntax:
passport.authenticate = sinon.stub( passport, 'authenticate' )
.returns(
( req, res, next ) => {
const user = {
username: 'test user',
email: 'testuser#mail.com',
displayName: 'Test User',
provider: 'testCase',
roles: [ 'admin' ]
}
req.user = user;
next()
}
);
Main things are:
add user data into req.user
execute next() for code flow to continue into next middleware
To recap this is not a way to actually test your authentication strategy but to bypass it in case you want to test router results.
I am trying to write a unit test for the following file named a.js
var express = require('express');
var router = express.Router();
router.get('/getHCQ', function (req, res) {
res.send("OK");
});
module.exports = router;
Unit test file : a.spec.js
var chai = require('chai');
var chaiHttp = require('chai-http');
var should = chai.should();
var a = require('./a');
describe('Unit Test', function () {
it('should run this', function (done) {
chai.request(a)
.get('/getHCQ')
.end(function(err, res) {
res.should.have.status(200);
done();
});
});
});
I am running it using Mocha but getting the following error :
Uncaught TypeError: Cannot read property 'apply' of undefined
at Immediate.<anonymous> (node_modules/express/lib/router/index.js:635:14)
Can someone please help me to figure out what am I doing wrong here?
Perhaps you forgot to configure chai with chai-http
var chai = require('chai');
var chaiHttp = require('chai-http');
var should = chai.should();
chai.use(chaiHttp); // <-- add this
var a = require('./a');
describe('Unit Test', function () {
it('should run this', function (done) {
chai.request(a)
.get('/getHCQ')
.end(function(err, res) {
res.should.have.status(200);
done();
});
});
});
i am using Express js and Mysql for my application, now i want to start unit testing. I have written this code:
var request = require('supertest');
var server = require('./app');
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('./app');
var should = chai.should();
chai.use(chaiHttp);
describe('loading express', function () {
it('responds to /', function testSlash(done) {
request(server)
.get('/')
.expect(200, done);
});
it('404 everything else', function testPath(done) {
request(server)
.get('/foo/bar')
.expect(404, done);
});
it('responds to /customers/getCustomerData', function testPath(done) {
request(server)
.get('/customers/getCustomerData?id=0987654321')
.end(function(err, res){
res.should.have.status(200);
res.body.should.be.a('object');
res.body.status.should.equal("success");
res.body.data.customerId.should.equal("0987654321");
done();
});
});
});
This code is working properly but it makes connection to database and checking all the test cases which i have written, but this is called integration testing i have to do unit testing using mock database. How can i achieve this mocking of database?
I am new to Mocha. Can someone suggest how to write test case for "retrieveEmployee" function.
var mysql = require('mysql');
var dbconfig = {
host:'localhost',
user:'root',
password:'root',
database:'db',
port:'3306'
};
exports.retrieveEmployee = function(req, res){
var connection = mysql.createConnection(dbconfig);
var query ='SELECT emp_Id, emp_Name FROM employee';
connection.query(query, function(err, rows, fields){
if(err)
throw err;
res.render('index', { title: 'Employee', 'items':rows });
});
};
I am using 'MySql' for database.
If your intent is to assert page renderings/functionality I'd use something like Zombie.
Ex:
app.js
app.get("/", function(req, res, next) {
res.render("index", {title: 'Hello World!'});
});
test/app.js
var Browser = require('zombie');
var app = require('../app');
describe("a html endpoin", function() {
var server;
beforeEach(function(done) {
server = app.listen(7331, done);
});
afterEach(function(done) {
server.close(done);
});
it("has some title", function(done) {
var browser = new Browser();
browser.visit("http://localhost:7331/")
.then(function() {
var title = browser.text('title');
assert.equal(title, 'Hello World!');
done();
});
});
});
If your intent is more of an API endpoint, then something like supertest would work nicely.
Ex:
app.js
app.get("/api", function(req, res, next) {
res.send({foo: 'bar'});
});
test/app.js
var request = require('supertest');
var app = require('../app');
describe("an api endpoint", function() {
it("returns some sort of json", function(done) {
request(app)
.get("/api")
.expect(200, {foo: 'bar'}, done);
});
});
However, both Zombie or supertest can be used to do both of these tasks.
Zombie
supertest
Use the assertion library of your choice.