How to implement functional unit testing sinon with mocks in NodeJs? - node.js

How to implement sinon.mock on follwing function.
function getDashboard(req,res){
res.send("success");
}
describe("GetDashboard test"){
it("Response Should be test", function(){
const getDashboard = sinon.stub().returns('success');
let req = {}
let res = {
send: function(){};
const mock = sinon.mock(res);
mock.expect(getDashboard.calledOnce).to.be.true;
mock.verify();
}
})
}
Also how to stubbing data in function.Is it correct way of mocking.

Here is a working example:
const sinon = require('sinon');
function getDashboard(req, res) { res.send('success'); }
describe("getDashboard", function () {
it("should respond with 'success'", function () {
const req = {};
const res = { send: sinon.stub() };
getDashboard(req, res);
sinon.assert.calledWithExactly(res.send, 'success'); // Success!
})
});
Details
getDashboard calls the send function of the res object that it is given, so you just need to create a mock object with a sinon stub for the send property and verify that it was called as expected.

Related

Mock api request Jest NodeJs

I'm trying to test the following code:
adapter.js
async function adapt(message) {
let parser = JSON.parse(message.content.toString());
let apiResult = await api(parser.id);
let result = apiResult.data.data;
return adapptedMessage = {"id": result.id}
}
This is my api call.
server.js
const axios = require('axios');
const url = process.env.URL;
function getApi(id) {
return axios.get(url + id).catch(function (error) {
if (error.response) {
// Request made and server responded
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// The request was made but no response was received
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
}});
}
module.exports = getApi
This is how I tried to test.
test.js
jest.mock('./server');
const axios = require('axios');
const adapt = require('./adapter');
describe("Adapter Test", () => {
test("adapt", async () => {
var result = await adapt(getMessage());
const mockResp = {"data":{"data": {"id":10}}};
axios.get = jest.fn(() => mockResp);
assert
expect(result).toStrictEqual(getOfferMessage());
});
})
function getMessage() {
return {"content":"{\"id\":10}"};
}
This is my first test in js, and I don't know how to mock the api call.
All I get is "undefined".
Could you help me?
Thanks
You should pass a factory function to jest.mock when mocking your server module
const mockResp = {"data":{"data": {"id":10}}};
jest.mock('./server', () => () => mockResp);
const adapt = require('./adapter');
describe("Adapter Test", () => {
test("adapt", async () => {
const result = await adapt(getMessage());
expect(result).toStrictEqual({ id: 10 });
});
})
function getMessage() {
return {"content":"{\"id\":10}"};
}

How to test class called or not using mocha & chai with sinon TDD?

I want to test class called or not in nodejs, mocha & chai with sinon. I tried with stub but not worked as what I expected.
someMiddleware.js
module.export.someMiddleware = async(req,res,next)=>{
const responseData = await someReturnFunction(req);
if (!responseData || responseData == null) {
throw new SomeExtendedErrrorClass("stringArg");
}
res.send(responseData);
}
testFile.js
sinon
.stub(someMiddleWare , "someReturnFunction")
.returns(null);
const stubClass = sinon.stub(SomeExtendedErrrorClass, "constructor");
someMiddleware(req, res, next);
expect(stubClass).to.have.be.called;
Even the SomeExtendedErrrorClass called, sinon not detected.
Sinon does not support stub standalone function or class imported from other modules. You need to use Link Seams, we will be using proxyquire to construct our seams.
E.g.
someMiddleware.js:
const someReturnFunction = require('./someReturnFunction');
const SomeExtendedErrrorClass = require('./SomeExtendedErrrorClass');
module.exports.someMiddleware = async (req, res, next) => {
const responseData = await someReturnFunction(req);
if (!responseData || responseData == null) {
throw new SomeExtendedErrrorClass('stringArg');
}
res.send(responseData);
};
SomeExtendedErrrorClass.js:
class SomeExtendedErrrorClass extends Error {}
someReturnFunction.js:
async function someReturnFunction() {
return 'real implementation';
}
someMiddleware.test.js:
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const SomeExtendedErrrorClass = require('./SomeExtendedErrrorClass');
chai.use(chaiAsPromised);
const { expect } = chai;
describe('68640048', () => {
it('should get and send response data', async () => {
const someReturnFunctionStub = sinon.stub().resolves('teresa teng');
const { someMiddleware } = proxyquire('./someMiddleware', {
'./someReturnFunction': someReturnFunctionStub,
});
const mReq = {};
const mRes = { send: sinon.stub() };
await someMiddleware(mReq, mRes);
sinon.assert.calledWithExactly(mRes.send, 'teresa teng');
});
it('should throw error', async () => {
const someReturnFunctionStub = sinon.stub().resolves(null);
const { someMiddleware } = proxyquire('./someMiddleware', {
'./someReturnFunction': someReturnFunctionStub,
});
const mReq = {};
const mRes = { send: sinon.stub() };
await expect(someMiddleware(mReq, mRes)).to.eventually.rejectedWith(SomeExtendedErrrorClass);
});
});
test result:
68640048
✓ should get and send response data
✓ should throw error
2 passing (10ms)

Sinon stub not working if tested using express app

I have a a controller function like below.
SendOTPController.js
const otpService = require('../services/otpService')
module.exports = async function(req, res) {
const {error, data} = await sendOTP(req.query.phone)
if(error)
return res.send(error)
return res.send(data)
}
otpService.js
module.exports = async function(phone) {
await result = fetch(`http://api.send-otp?phone=${phone}`)
if (result !== sucess)
return {
error: "Failed to send OTP!"
data: null
}
return {
error: null
data: result
}
}
Below is my test.
const expect = require('chai').expect
const request = require('supertest')
const sinon = require('sinon')
const rewire = require('rewire')
const SendOTPController= rewire('../../src/controllers/SendOTPController')
const app = require('../../src/app')
describe('GET /api/v1/auth/otp/generate', function () {
it('should generate OTP', async () => {
let stub = sinon.stub().returns({
error: null,
data: "OTP sent"
})
SendOTPController.__set__('sendOTPOnPhone', stub)
const result = await request(app)
.get('/api/v1/auth/otp/generate?phone=8576863491')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
console.log(result.body)
expect(stub.called).to.be.true
})
})
In above code the stub is not being called.
But if use only controller without using express app it works fine.
const expect = require('chai').expect
const request = require('supertest')
const sinon = require('sinon')
const rewire = require('rewire')
const SendOTPController= rewire('../../src/controllers/SendOTPController')
const app = require('../../src/app')
describe('GET /api/v1/auth/otp/generate', function () {
it('should generate OTP', async () => {
let stub = sinon.stub().returns({
error: null,
data: "OTP sent"
})
SendOTPController.__set__('sendOTPOnPhone', stub)
const result = await SendOTPController() // not using express app, hence not passing req, res
console.log(result)
expect(stub.called).to.be.true
})
})
I went through many modules and docs.
They give a solution how I can stub a module.exports = async function(){}.
They also work, but only If they are directly imported and tested.
They don't work if I use it with express app.
Any help would be appreciated, thanks.
Instead of returns try to use resolves:
let stub = sinon.stub().resolves({
error: null,
data: "OTP sent"
})
returns is for sync code, resolves for async.

Unit test with promise handling - node.js

i want to do a unit test with async function on the code. and here is my code on user.test.js
'use strict'
const UserDomain = require("../../../../../../bin/modules/users/repositories/commands/domain")
const UserHandler = require("../../../../../../bin/modules/users/repositories/commands/command_handler")
const expect = require('chai').expect;
const assert = require('chai').assert;
const sinon = require('sinon');
describe('User domain', () => {
describe('".login(data)"', () => {
let user;
beforeEach( () => {
user = {
clientId : "adithyavisnu",
clientSecret : "secretOfmine#19"
}
});
it("should return error when username/password is empty", (done)=> {
done();
// let
})
it("should return object", async () => {
const domainStub = sinon.stub(UserDomain.prototype, 'login');
const result = await UserHandler.login(user);
sinon.assert.calledOnce(domainStub);
domainStub.restore();
})
});
});
If the normal code (not the unit test code above) the const result = await UserHandler.login(user); will have an object response, but when i do in user.test.js it do not get the response. the result is undefined.
here are the user_handler code
'use strict';
const User = require('./domain');
const login = async (data) => {
const postData = async () => {
const user = new User();
const result = await user.login(data);
return result;
}
const response = await postData();
return response;
}
Is there something i did wrong on the code or some code is missing?
I am sorry if you do think there is unclear information
Thank you for the responses
In the normal flow, the UserHandler calls the Domain.login method and returns the result object. When you run the unit test you are stubbing the Domain.login method. so, it wont return the result as normal flow. You can either make the stub return some result object and test that or just spy the Domain.login instead of stubbing it , if you just want to just check that the Domain.login was called without altering its behavior. Read more on stubs/spies here if you would like - http://sinonjs.org/releases/v1.17.7/stubs/

Unit test mongoose promises with sinon

I am trying to unit test a mongoose object that uses promises. I have written the test below and it works but it's not complete. I can't figure out how to test if the 'then' or 'catch' methods are called.
How can I use a spy to check that the 'then' method is called when I resolve the promise?
Method to test
export function create(req, res) {
User
.createAsync(req.body)
.then(handleCreate(res, req.originalUrl))
.catch(handleError(res));
}
Unit test
it('should do something', () => {
const req = {
body: 45,
};
const res = {};
const mockRole = sandbox.mock(Role).expects('createAsync').once().withArgs(45)
.returns(Promise.resolve());
controller.create(req, res);
});
UPDATE WITH SOLUTION I USED (May 6th, 2016)
Thanks #ReedD for helping me in the right direction
Although this "works", I feel like I'm testing the functionality of promises more than my code.
it('should call create with args and resolve the promise', () => {
const createSpy = sinon.spy();
const errorSpy = sinon.spy();
sandbox.stub(responses, 'responseForCreate').returns(createSpy);
sandbox.stub(responses, 'handleError').returns(errorSpy);
sandbox.mock(Role).expects('createAsync').once().withArgs(45)
.returns(Promise.resolve());
return controller.create(req, res).then(() => {
expect(createSpy.calledOnce).to.be.equal(true);
expect(errorSpy.calledOnce).to.be.equal(false);
});
});
You could add handleCreate and handleError to module.exports and then make stubs or spys of those. Below is an example of what I think you're trying to do. I also assumed you were using sinon/chai.
http://ricostacruz.com/cheatsheets/sinon-chai.html
// controller.js
module.exports = {
handleCreate: function () {
// ..code
},
handleError: function () {
// ..code
},
create: function (req, res) {
User
.createAsync(req.body)
.then(this.handleCreate(res, req.originalUrl))
.catch(this.handleError(res));
}
};
// test/test.js
var controller = require('../controller');
it('should do something', function (done) {
var handleCreate = sandbox.spy(controller, 'handleCreate');
var handleError = sandbox.spy(controller, 'handleError');
var mockRole = sandbox
.mock(Role)
.expects('createAsync')
.once().withArgs(45)
.returns(Promise.resolve());
var req = {
body: 45,
};
var res = {
send: function () {
expect(handleCreate).to.be.calledOnce;
expect(handleError).to.not.be.called;
done();
}
};
controller.create(req, res);
});

Resources