Jest is not calling function correct number of times - javascript

I am mapping over an array and then calling an external function. example
['error1', 'error2'].map(err => myFunc())
then in my jest test I am saying, expect myFunc() to have been called 2 times
but it's saying it is only called once
it's an external function defined as such
export const myFunc = () => {}
then when I import im doing
import { myFunc } from 'file/path'
jest.mock('file/path', () => ({
myFunc: jest.fn(),
}))
expect(myFunc.mock.calls).toHaveLength(2)
anyone see what I'm doing wrong? really makes no sense as function should be called for every item in array :/

Related

In Jest, how to test a function declared inside a function?

I am trying to test a function that is declared inside another function(Parent). I tried a few things but was not able to test that. I am using react library and JEST testing framework in the project.
Here is the service file (service.ts) function which I am trying to test:
import { useThisHook } from './base-hooks';
export function someFunction(param: string) {
const [
resolveFunction,
,
{ loading, error },
] = useThisHook();
const childFun = (param : number) => {
resolveFunction(someArguments);
}
return{
someValue: childFun
}
}
Here is the spec file code:
import * as SomeHooks from './base-hooks';
import * as Service from './service';
describe('Service function', () => {
beforeEach(() => {
jest.spyOn(SomeHooks, 'useThisHook').mockReturnValue(
{
//Some Value
}
);
});
test('Some function test', () => {
const someFunctionResponse = Service.someFunction('string');
expect(someFunctionResponse).toEqual({
someValue: expect.any(Function),
});
});
});
Till here it is fine. Tests are also getting passed but the problem is that childFn is not getting the coverage and that's what my requirement is. I am new to React and Jest. I am not able to understand how can I achieve that. I tried many things but didn't succeed.
Your childFn is not being called, that's why it's not getting coverage.
You could either refactor the whole childFn to a new hook and test it individually with something like react-hooks-testing-library.
Or you could separate the childFn and declarate it outside the someFunction scope pass the resolveFunction and then test it.
You only get coverage if the code is actually called, not when it is declared.

Using a function defined inside an exports function, from another file

I have some code like this in a file helperFunctions.js:
exports helperFunctions = () => {
const functionA = async(args) => {
console.log(args);
};
const functionB = async(args) => {
functionA(myArg);
};
}
How can I call functionA and functionB from a separate file altogether, say, main.js?
I've tried:
import { helperFunctions } from './helperFunctions';
//...some code
helperFunctions.functionA('hello');
// OR
functionA('hello');
The specific error is:
TypeError: _helperFunctions.helperFunctions.functionA is not a function
and when trying the second solution, it's:
ReferenceError: functionA is not defined
I'm trying to avoid importing literally every single function I'm using (by way of exporting every single function I'm using). I'd like to do something like helperFunctions.function for the functions I need.
It really need to be a function? You could export an Object:
// helperFunctions.js
let helperFunctions = {
functionA: async (args) => {
console.log(args);
},
functionB: async (args) => {
functionA(myArg);
}
}
exports helperFunctions;

Nested describe and behaviour of dynamically created "it"s

I have nested describes in my tests and as usual I am using some beforeEach and before in describes. And one of my describe function calls helper function which creates dynamic tests (DRY). And mocha runs description of nested describe before beforeEach method. And my dynamically created it has comp as undefined.
const checkProps = (comp, propName, expectedvalue) => {
it(`${comp} should have ${propName} equal to ${expectedvalue}`, () => {
expect(comp.prop(propName)).to.equal(expectedvalue);
});
};
describe('Component', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<MyComponent />);
});
describe('prop checking', () => {
checkProps(wrapper, 'title', 'SomeTitle');
});
});
What is the best way todo it? Thanks in advance.
What happens
The Mocha Run Cycle runs all describe callback functions first (...which is also true for other testing frameworks such as Jest and Jasmine).
Then it runs the before hooks, then beforeEach hooks, and finally the it callbacks.
So checkProps runs as part of running the initial describe callbacks, and at that point wrapper is undefined, so as you have noticed the test description says undefined should have....
The beforeEach hook runs before the it callback function runs...but it redefines wrapper so when the it callback runs comp is still undefined and the test fails:
1) Component
prop checking
undefined should have title equal to SomeTitle:
TypeError: Cannot read property 'prop' of undefined
at Context.prop (test/code.test.js:15:19)
Solution
A couple of things need to be changed:
The component name needs to be available when it runs and at that point wrapper doesn't exist yet so you'll have to pass the name yourself.
If you pass an object to checkProps then you can set a wrapper property on the object during beforeEach and access that wrapper property within your test since the object is never redefined.
Here is a working test that should get you closer to what you are trying to do:
import * as React from 'react';
import { shallow } from 'enzyme';
const MyComponent = () => (<div title="SomeTitle">some text</div>);
const checkProps = (name, obj, propName, expectedvalue) => {
it(`${name} should have ${propName} equal to ${expectedvalue}`, () => {
expect(obj.wrapper.prop(propName)).to.equal(expectedvalue); // Success!
});
};
describe('Component', () => {
const obj = {};
beforeEach(() => {
obj.wrapper = shallow(<MyComponent />);
});
describe('prop checking', () => {
checkProps('MyComponent', obj, 'title', 'SomeTitle');
});
});

Sinon spy callCount property returns 0 on some tests

This is my code:
// SUT.spec.js
import * as myModule from './myModule';
describe('my issue', () => {
let myFuncSpy = sinon.spy(myModule, 'myFunc');
beforeEach(() => {
myFuncSpy.reset();
});
it('my case A', () => {
SUT.methodA();
expect(myFuncSpy.callCount).to.equal(1); // fails, it says it's 0
});
it('my case B', () => {
SUT.methodB();
expect(myFuncSpy.callCount).to.equal(1); // passes
});
});
In my module, both method calls myFunc, however only on methodA it's not being registered:
// SUT.js
import { myFunc } from './myModule';
export function methodA() {
myFunc(....);
console.log(myFunc.callCount); // Mocha output shows 1
};
export function methodB() {
myFunc(....);
console.log('method B ran'); // Mocha output shows this line
console.log(myFunc.callCount); // Mocha output shows 1
};
Basically there is no apparent difference in the way the spy is being called. I'm very confused as what could be possible wrong.
I added the console.log statement inside the SUT just to make sure the spy was properly set (otherwise it wouldn't have a property called callCount). Also, if I comment out the .reset() call, the log statement shows undefined instead of 1 or another number.
What could be wrong in here? This is of course a simplified version of the actual SUT. However, the console.log statements show that the problem is definitely not that the lines are not being executed.
You have to await your asynchronous methods before asserting.

Sinon stub has weird behavior when used with mocha watch

So here's the basic setup we have
src/MyComponent.js
import actions from `src/actions`
export const mapDispatchToProps = dispatch => {
return {
onClick: () => {
dispatch(actions.myAction())
}
}
}
src/actions.js
const actions = {
myAction: () => () => ...
}
export default actions
src/MyComponentTest.js
import sinon from 'sinon'
import actions from 'src/actions'
import { mapDispatchToProps } from 'src/MyComponent'
describe('onClickTests, () => {
let dispatch = sinon.spy()
let onClick
beforeEach(() => {
onClick = mapDispatchToProps(dispatch).onClick
})
it('calls dispatch with myAction', () => {
function f () {}
sinon.stub(actions, 'myAction').returns(f)
onClick()
expect(dispatch.args[0]).to.deep.equal([f])
})
})
Basically, we're checking that the onClick function is calling dispatch with the return value of actions.myAction. Since the real actions.myAction returns an anonymous function, we're stubbing it to return the function f. When we run this with Mocha everything works, until we run with --watch. The first run still passes as expected, but when we save a test and the tests are re-run, this tests fails with
expected [ [Function: f] ] to deeply equal [ [Function: f] ]
If I made these changes to the test
it('calls dispatch with myAction', () => {
function f () {}
sinon.stub(actions, 'myAction').returns(2)
onClick()
expect(dispatch.args[0]).to.deep.equal([2])
})
I get
expected [ [Function: f] ] to deeply equal [ [2] ]
So what I gather from this is that on the second run, the f that actions.minimize returned was the "old" f from the first run. We've tried a wide variety of different variations on this like using module.exports/require instead of export/import and moving things around into Mocha hooks (beforeEach, etc) and nothing seems to be working, which leads me to believe this is a more fundamental issue with how we're testing. Any suggestions?
I've faced this issue before and it took a while to figure it out.
Not sure if that's your case, but I was using .jsx extensions for my components and turns out this brings all sorts of random problems.
Renaming Component.jsx to Component.js solved it.

Categories

Resources