Mock function without callback as parameter - jestjs

I have dh.js
const checkDExistsCallback = (err, dResp) => {
if (err)
cbResp.error('failed');
if (dResp.length > 0)
checkDCollectionExists();
else
cbResp.error('Not found.');
};
const checkDCollectionExists = () =>
{
let query = `select sid from tablename where sid = '${objRequestData.dName}' limit 1;`;
genericQueryCall(query, checkDCollCallback);
}
module.exports = {checkDExistsCallback , checkDCollectionExists }
In my dh.test.ts
const dhExport = require("./DensityHookReceive");
dhExport.checkDCollectionExists = jest.fn().mockImplementation(() => {});
test('check req dh is exists', () => {
dhExport.checkDExistsCallback(false, '[{}]');
expect(dhExport.checkDCollectionExists).toBeCalled();
});
In dh.js checkDExistsCallback function is invoked the checkDCollectionExists after satisfied the 'if' condition. When you look into the dh.test.ts file I mocked the checkDCollectionExists function in the beginning, but while running the test it did not invoke the mocked function it invokes the actual function. Can you help me to figure it out?

A function that is used in the same module it was defined cannot be mocked, unless it's consistently used as a method on an object that could be mocked, e.g.
if (dResp.length > 0)
module.exports.checkDCollectionExists();
instead of
if (dResp.length > 0)
checkDCollectionExists();
checkDCollectionExists needs to be either moved to another module, or two functions need to be tested as a single unit. It's database call that needs to be mocked.

Related

Jest spy.On() does not call the method in React Js

I write a test for a method:
const methods = {
run: (name) => {
console.log('run');
return name;
}
}
Using const testMethod = jest.spyOn(methods, 'run').mockResolvedValue({});, the console.log('run') is not triggered, but if i write: const testMethod = jest.spyOn(methods, 'run');, the console.log() is triggered. Why in the first case the console.log() is not triggered and how to solve this?
When you use mockResolvedValue, you are replacing your function with a stub. As the purpose of a stub is not to execute the real implementation of the function but just to return a fictitious value, this behavior is normal.
jest.fn().mockResolvedValue({})
is equivalent to:
jest.fn().mockImplementation(() => Promise.resolve({}));
https://jestjs.io/docs/mock-function-api#mockfnmockresolvedvaluevalue
Update:
If you want to verify if your function is called and if it returned a specific value, then:
const spy = jest.spyOn(methods, 'run');
const myName = 'John Doe';
// Call the method...
expect(spy).toBeCalled();
expect(spy).toHaveReturnedWith(myName);

how to test a Module in NodeJs without function in it?

I have read and tried many ways to do this,I have a module like below .
//echo.js
module.exports = (services, request) => {
logger.debug('excecuting');
return true;
};
I want to write unit test for this module using sinon , what i did tried so far is.
describe('test', function() {
const echo1 = require('./echo');
var spy1 = sinon.spy(echo1);
beforeEach(() => {
spy1.resetHistory();
});
it('Is function echo called once - true ', done => {
echo1(testData.mockService, testData.stubRequest); //calling module
spy1.called.should.be.true;
done();
});
});
i get the below output which is failed, though i see my function being called in the output window
1) test
Is function echo called once - true :
AssertionError: expected false to be true
+ expected - actual
-false
+true
at Context.done (echo_unit.js:84:27)
could anyone tell me how to test modules in nodejs
It doesn't matter in this case whether it's a module or just a function.
A function that isn't called as a method can't be spied (also, describe function isn't a proper place to place var spy1 = sinon.spy(echo1)). This also isn't needed here because it's you who call the function, there's no need to test that it was called.
Since all that echo does is calls logger.debug and returns true, this needs to be tested:
it('Is function echo called once - true ', () => {
sinon.spy(logger, 'debug');
const result = echo1(testData.mockService, testData.stubRequest);
expect(logger.debug).to.have.been.calledWith("execute");
expect(result).to.be(true);
// the test is synchronous, no done() is needed
});

Get the value of a promise and assign to variable

utility.fetchInfo() returns a Promise object. I need to be able to get the value of this Promise object and assign the value of it to a variable that I can then use later on in my code.
At the moment, I can happily print the value of result to the console, but I need to be able to assign this value to myVal. So far, I've tried a lot of things and nothing has worked.
var myVal = utility.fetchInfo().then(result => console.log(result));
Thanks
What #dhilt said but do your stuff inside the promise callback function:
utility.fetchInfo().then(result => {
doSomethingWith(result);
});
Or use async/await if you are using a recent version of Node or Babel:
async function myFunction () {
var myVal = await utility.fetchInfo();
}
Just do an assignment within the callback's body
utility.fetchInfo().then(result => { myVal = result; });
Depends on the situation, for example, if there's a big piece of async logic, it may be better to extract it in a separate function:
let myVal; // undefined until myAsyncFunc is called
const myAsyncFunc = (result) => {
console.log(result);
myVal = result;
// ...
};
utility.fetchInfo().then(myAsyncFunc); // async call of myAsyncFunc
When you return the value to another file/function and you are getting undefined because another function where you are using that value is not waiting for the value to be assigned to the variable. For example there are two function
function1(){
var x=desired_value
}
function2(){
var y = x
}
now function1 might take some time to assign desire value to var x and java script ll not wait for this, it ll start running function2 and when you read the value of y you will get undefined.
To solve this problem we can use java script promise/await/async, return value from async function as resolve. refer below example
async function1(){ //function1 should be async here for this to work
return new Promise(function(resolve,reject){
resolve(desired_value)
});
}
or above function can be writtern as
async function1(){ //function1 should be async here for this to work
return Promise.resolve(desired_value)
}
Now we can use this value in another function by calling the function1 and use await keyword
function2(){
var y = await function1();
}
now it ll wait for function1 to complete before assigning its value to y.
I think what you are looking for is some fancy ES7 syntax:
var myVal = (async () => {
var data = await utility.fetchInfo();
return data;
})();
(async () => {
console.log(await myVal);
})();
Keep in mind console.log(myVal) will end up with Promise { <pending> }, So instead you would use
(async () => {
console.log(await myVal);
})();
which would return your desired output.

How to get `this` in jest mock function

I have the below code, which mocks a function fetchAge of Person. I need to conditionally return a value based on the value of this, but this is an empty object in the function. Is there any way to do this in Jest?
jest.unmock('Person');
const Person = require('Person');
Query.prototype.fetchAge = jest.fn(() => {
console.log(this); // this returns an empty object
if(this.name === 'Bob') return 21;
if(this.name === 'Joe') return 19;
});
test('verify correct ages', function() {
const bob = new Person('Bob');
expect(bob.fetchAge).toEqual(21);
});
If you don't need to assert anything on the mocked fetchAge method (like fetchAge.mock.calls.length for example) you could simply assign the fetchAge method to a new function without using jest.fn.
E.g.
Query.prototype.fetchAge = () => {
console.log(this); // this returns an empty object
if(this.name === 'Bob') return 21;
if(this.name === 'Joe') return 19;
};
I think that way this will relate to the correct object (here bob).

Testing Promises with multiple thens using testdoublejs

I am using testdouble for stubbing calls within my node.js project. This particular function is wrapping a promise and has multiple then calls within the function itself.
function getUser (rethink, username) {
return new Promise((resolve, reject) => {
let r = database.connect();
r.then(conn => database.table(tablename).filter({username}))
.then(data => resolve(data))
.error(err => reject(err));
});
}
So I am wanting to determine if the resolve and reject are handled correctly based on error conditions. Assume there is some custom logic in there that I need to validate.
For my test
import getUser from './user';
import td from 'testdouble';
test(t => {
const db = td.object();
const connect = td.function();
td.when(connect('options')).thenResolve();
const result = getUser(db, 'testuser');
t.verify(result);
}
The issue is that the result of connect needs to be a promise, so I use then resolve with a value which needs to be another promise that resolves or rejects.
The line it is relating to is the result of database.connect() is not a promise.
TypeError: Cannot read property 'then' of undefined
Anyone have success with stubbing this type of call with Test Double?
So figured out the resolution. There are a few things to note in the solution and that we encountered. In short the resolution ended up being this...
td.when(database.connect()).thenResolve({then: (resolve) => resolve('ok')});
This resolves a thenable that is returned when test double sees database connect. Then subsequent calls can also be added.
There is also a part to note if you send in an object to database.connect() you have to be aware that it is doing === equality checking and you will need to have a reference to that object for it to correctly use td.when.
Test double provides stubs for unit testing. And in your case 'db' is the object we need to mock. Creating the mocking db through
td.object(Database) // Database is the class or constructor of your db
will be the right choice, but to simply mock those methods you need in this case, I wouldn't pick that way.
Here's the tested module, 'some.js':
function getUser (database, username) {
return new Promise((resolve, reject) => {
let r = database.connect();
r.then(conn => database.table('table').filter({username:username}))
.then(data => resolve(data))
.catch(err => reject(err));
});
}
module.exports = getUser;
And the test file, using mocha and chai.expect, which is could also be any other unit test module here:
let td = require('testdouble');
let expect = require('chai').expect;
const getUser = require('./some');
describe('some.js',()=>{
it('getUser',()=>{
const db = {};
const name = 'name';
db.connect = td.function();
db.table = td.function('table');
db.filter = td.function('filter');
td.when(db.connect()).thenResolve(db);
td.when(db.table('table')).thenReturn(db);
td.when(db.filter({username: name})).thenResolve('some user data');
return getUser(db, name)
.then(user=>{
expect(user).to.equal('some user data')
})
.catch(e=>assert(e))
})
})
So please let me know if any of these confuse you.

Resources