Fail mocha test in catch block of rejected promise - node.js

How to fail the test in catch block of promise rejection when making http call using axios?
Adding expectations, asserts, should expressions in catch block doesn't help.
The test is passing.
I's run using .\node_modules\.bin\mocha
let chai = require('chai');
var expect = chai.expect;
var axios = require('axios')
var instance = axios.create({})
describe('test', () => {
context('test', () => {
it('should succeed', () => {
let url = 'url'
instance.get(url)
.then(function(response) {
expect(response.data).not.to.be.null
} )
.catch(function(err) {
console.error(err.data)
// should fail the test
})
})
})
})

If You want to verify my suggestions, replace url value with valid url (ex: https://google.com)
You can try several ways:
1) Using assert.fail()
const axios = require('axios');
const { assert, expect } = require('chai');
const instance = axios.create({})
describe('test', () => {
context('test', () => {
it('should succeed', () => {
let url = 'abc'
return instance.get(url)
.then((res) => {
expect(res.data).not.to.be.null;
})
.catch((err) => {
assert.fail('expected', 'actual', err);
});
});
});
});
2) Using done() with error object
const axios = require('axios');
const { expect } = require('chai');
const instance = axios.create({})
describe('test', () => {
context('test', () => {
it('should succeed', (done) => {
let url = 'abc'
instance.get(url)
.then((res) => {
expect(res.data).not.to.be.null;
done();
})
.catch((err) => {
done(err);
});
});
});
});
3) Simply just throw an error :)
const axios = require('axios');
const { expect } = require('chai');
const instance = axios.create({})
describe('test', () => {
context('test', () => {
it('should succeed', () => {
let url = 'abc'
return instance.get(url)
.then((res) => {
expect(res.data).not.to.be.null;
})
.catch((err) => {
throw err;
});
});
});
})
If You want to check if that method fails at all and You expect this, go that way (it requires chai-as-promised package):
const axios = require('axios');
const chai = require('chai');
chai.use(require('chai-as-promised'));
const instance = axios.create({})
describe('test', () => {
context('test', () => {
it('should succeed', () => {
let url = 'abc'
return chai.expect(instance.get(url)).to.be.rejected;
});
});
});

Related

Change jest mock on class for single test

I have an issue where I want to change what a class method returns for a single test while testing a different module. I have the following:
testingModule.test.js
const { testingModuleMethod } = require('../testingModule')
jest.mock('../helperClass', () =>
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
describe('testingModule.js', () => {
describe('testingModuleMethod', () => {
describe('when errors', () => {
const consoleSpy = jest.spyOn(console, 'error');
// SOMETHING NEEDS TO GO HERE TO CHANGE THE jest.mock ON LINE 3
await expect(testingModuleMethod(data)).rejects.toThrow('Error');
expect(consoleSpy).toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
});
testingModule.js
const HelperClass = require('./helperClass');
const testingModuleMethod = async (data, callback) => {
try {
const objectToEvaluate = data.object;
const helperClassInstance = new HelperClass();
await helperClassInstance.helperClassMethod(objectToEvaluate);
log('info', "Success!");
callback(null, {});
} catch(error) {
log('error', 'Something went wrong')
}
};
No matter what I put in there I either get an error with the code (undefined) or it just ignores it and resolves due to the mock at the start. I have tried adding a spy as well as importing the class and using the prototype override.
I'm using node and "jest": "^27.0.6"
I have managed to answer this by doing the following:
Firstly I discovered that to mock a class like that I have to add a jest function into the mock like so:
describe('testingModuleMethod', () => {
describe('when errors', () => {
const consoleSpy = jest.spyOn(console, 'error');
HelperClass.mockImplementation(() => ({
helperClassMethod: jest.fn(() => { throw new Error('Error') })
}));
await expect(testingModuleMethod(data)).rejects.toThrow('Error');
expect(consoleSpy).toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
This also had a knock on effect to the rest of the tests though so I added a beforeEach at the start that looks like:
HelperClass.mockImplementation(
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
Finally I needed to require the class. The overall test looks like this now and works:
const { testingModuleMethod } = require('../testingModule');
const HelperClass = require('./helperClass');
jest.mock('../helperClass', () =>
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
describe('testingModule.js', () => {
beforeEach(() => {
HelperClass.mockImplementation(
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
});
describe('testingModuleMethod', () => {
describe('when errors', () => {
const consoleSpy = jest.spyOn(console, 'error');
HelperClass.mockImplementation(() => ({
helperClassMethod: jest.fn(() => { throw new Error('Error') })
}));
await expect(testingModuleMethod(data)).rejects.toThrow('Error');
expect(consoleSpy).toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
});

Cant clear database after tests are run on Mocha and Chai using mongodb with mongoose in my node.js app

I will include both the files that are needed for the same
the main issue is that after every test I run I want no more entries to be added in my database and it should be cleaned after the test are done
so I used aftereach() but I suppose it is not working because of something wrong I did, can you help me with that.
here is my test.js
process.env.NODE_ENV = 'test';
// const mongoose = require('mongoose');
const chai = require('chai');
const chaiHttp = require('chai-http');
const Task = require('../config/model');
const server = require('../index');
const { expect } = chai;
chai.use(chaiHttp);
describe('Task', (done) => {
afterEach(() => {
Task.crud.drop();
done();
});
});
// Test Get Tasks
describe('/GET tasks', () => {
it('it should GET all the tasks', async () => {
const res = await chai.request(server)
.get('/task');
// .end((err, res) => {
expect(res).to.have.status(200);
// expect(res.body).to.be.a('array');
// done(err);
});
});
describe('/Post tasks', () => {
it('should Post the task', async () => {
const taskPost = {
task: 'run as fast as possible you idiot',
};
const res = await chai.request(server)
.post('/task')
.send(taskPost);
// .end((err, res) => {
expect(res).to.have.status(200);
// done();
});
});
describe('/GET/:ID', () => {
it('should Get the task by ID', async () => {
const tasks = new Task({ task: 'The Lord of the Rings' });
const task = await tasks.save();
const res = await chai.request(server)
.get(`/task/${task.id}`)
.send(task);
// .end((error, res) => {
expect(res).to.have.status(200);
// done();
// });
});
});
describe('/PUT/:ID task', () => {
it('it should UPDATE a task given the id', async () => {
const tasks = new Task({ task: 'The Chronicles of Narnia' });
const task = await tasks.save();
const res = await chai.request(server)
.put(`/task/${task.id}`)
.send({ task: 'The Chronicles of Sarvesh' });
// .end((error, res) => {
expect(res).to.have.status(200);
// });
});
});
and the files that is in /config/model
const mongoose = require('mongoose');
const Schema = new mongoose.Schema({
task: {
type: String,
required: true,
},
});
module.exports = mongoose.model('crud', Schema, 'crud');
I don't think model has any inbuilt drop method. You need to either use db.collection("collectionName").drop() for which you need handle of current db or use deleteMany and delete everything inside the collection. something like this
describe('Task', (done) => {
afterEach(() => {
Task.crud.deleteMany({}, (err, response) => {
done();
});
});
});

sinon: Cannot stub non-existent own property formatData

I'm getting the error 'Cannot stub non-existent own property formatData' but i've honestly no idea why! I'm quite new to testing and this test is the same as another one i've done which worked.
const submitDetails = require('../src/scripts/submitDetails')
const sendEmail = require('../src/lib/sendEmail')
describe('submitDetails', function () {
let sandbox = null
before(() => {
sandbox = sinon.createSandbox()
})
afterEach(() => {
sandbox.restore()
})
describe('submitDetails', () => {
let mockParams, result
beforeEach(async () => {
mockParams = {
emailName: 'Confirmation',
formName: 'Contact'
}
sandbox.stub(submitDetails, 'formatData').returns({})
result = await submitDetails.formatData(mockParams)
})
it('should call formatData', () => {
expect(submitDetails.formatData).to.be.calledWith(mockParams)
})
it('should return lowercase params', () => {
expect(result).to.deep.equal({
emailName: 'confirmation',
formName: 'contact'
})
})
it('should call sendEmail', () => {
expect(sendEmail.sendEmail).to.be.calledWith(result)
})
})
describe('formatData', () => {})
})

How can I mock fetch function in Node.js by Jest?

How can I mock fetch function in Node.js by Jest?
api.js
'use strict'
var fetch = require('node-fetch');
const makeRequest = async () => {
const res = await fetch("http://httpbin.org/get");
const resJson = await res.json();
return resJson;
};
module.exports = makeRequest;
test.js
describe('fetch-mock test', () => {
it('check fetch mock test', async () => {
var makeRequest = require('../mock/makeRequest');
// I want to mock here
global.fetch = jest.fn().mockImplementationOnce(() => {
return new Promise((resolve, reject) => {
resolve({
ok: true,
status,
json: () => {
return returnBody ? returnBody : {};
},
});
});
});
makeRequest().then(function (data) {
console.log('got data', data);
}).catch((e) => {
console.log(e.message)
});
});
});
I tried to use jest-fetch-mock, nock and jest.mock but failed.
Thanks.
You can mock node-fetch using jest.mock. Then in your test set the actual mock response
import fetch from 'node-fetch'
jest.mock('node-fetch', ()=>jest.fn())
describe('fetch-mock test', () => {
it('check fetch mock test', async () => {
var makeRequest = require('../mock/makeRequest');
const response = Promise.resolve({
ok: true,
status,
json: () => {
return returnBody ? returnBody : {};
},
})
fetch.mockImplementation(()=> response)
await response
makeRequest().then(function (data) {
console.log('got data', data);
}).catch((e) => {
console.log(e.message)
});
});
});
import fetch, { Response } from 'node-fetch';
jest.mock('node-fetch');
describe('fetch-mock test', () => {
const mockFetch = fetch as jest.MockedFunction<typeof fetch>;
it('check fetch mock test', async () => {
const json = jest.fn() as jest.MockedFunction<any>;
json.mockResolvedValue({ status: 200}); //just sample expected json return value
mockFetch.mockResolvedValue({ ok: true, json } as Response); //just sample expected fetch response
await makeRequest();
expect(json.mock.calls.length).toBe(1);
})
})

Async Await Node js

I am learning async await using node js
var testasync = async () =>
{
const result1 = await returnone();
return result1;
}
testasync().then((name)=>{
console.log(name);
}).catch((e) =>{
console.log(e);
});
var returnone = () =>{
return new Promise((resolve,reject)=>
{
setTimeout(()=>{
resolve('1');
},2000)
})
}
It fails with returnone is not a function. What am i doing wrong? calling the function just by itself work
returnone().then((name1) => {
console.log(name1)
})
Just calling the above code works
The reason you are getting this error because of hoisting. Your code seen by JS would look like this
var returnone;
var testasync = async () => {
const result1 = await returnone();
return result1;
}
testasync().then((name) => {
console.log(name);
}).catch((e) => {
console.log(e);
});
returnone = () => {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve('1');
}, 2000)
})
}
So the value of returnone is undefined.
You are assigning the function to the variable returnone at the end of the code, but you are trying to call that function before this assignment. You have two options to fix the code:
Option 1
Use a function declaration; this way, the function is hoisted and you can use it right from the start:
var testasync = async () => {
const result1 = await returnone();
return result1;
}
testasync().then((name) => {
console.log(name);
}).catch((e) => {
console.log(e);
});
function returnone() {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve('1');
}, 2000)
})
}
Option 2
Assign the function to the variable before you try to call it:
var returnone = () => {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve('1');
}, 2000)
})
}
var testasync = async () => {
const result1 = await returnone();
return result1;
}
testasync().then((name) => {
console.log(name);
}).catch((e) => {
console.log(e);
});

Resources