I am trying to verify that a function within a module calls another function within that module. When I try the following, Jest reports that bar was called 0 times. How can I test the function call successfully?
// module.js
function foo() {
bar()
}
function bar() {
...
}
export {foo, bar}
// __tests__/module-test.js
import * as module from "../module";
test("foo calls bar", () => {
module.bar = jest.fn();
module.foo();
expect(module.bar).toHaveBeenCalledTimes(1)
})
Related
My mocked utilFunction isn't being used and adding logging to the factory function shows that it's never called. I've already tried searching for jest.mock not working with relative paths and jest.mock not being called for Typescript thinking that it might be related to the mix of JS tests and TS source code or to the different module paths used in the source vs test code.
Code being tested:
// src/foo/fooModule.ts
import { utilFunction } from '../util'
export const foo = () => {
return utilFunction()
}
Test code:
// test/fooModule.test.js
const { foo } = require('../src/foo/fooModule')
jest.mock('../src/util', () => {
return { utilFunction: () => 'mocked' };
});
describe('fooModule tests', () => ...)
The jest.mock call needs to be moved above the imports:
// test/fooModule.test.js
jest.mock('../src/util', () => {
return { utilFunction: () => 'mocked' };
});
const { foo } = require('../src/foo/fooModule')
describe('fooModule tests', () => ...)
My last experience working with Jest prior to this was in a project where the tests were also written in Typescript and babel-jest was used. babel-jest includes babel-jest-hoist which hoists the jest mocks above any imports automatically, so I didn't previously have to worry about the ordering.
Say we have a util.js contains functions a and b:
// util.js
export function a() {
...
}
export function b() {
...
}
And I require them in index.js:
// index.js
export default function main() {
const {a, b} = require('./util');
...
a(); // use them somewhere
b();
}
But I want to replace the require function to its source code like this before the bundling:
// replaced index.js
export default function main() {
const a = function () {
// ... source code from util.js
};
const b = function () {
// ... source code from util.js
};
...
a(); // use them somewhere
b();
}
I'm not that familiar with webpack plugins and hooks API.
Is this possible and if yes, how to do it?
Thanks!
One solution not that clever, do string replace directly by string-replace-loader.
Using Rewire for testing..
Rewire is failing to rewire, and I'm wondering why.
Here is an example of rewire failing:
A file has a few exported functions...
export function foo() {}
export function bar() {}
export function baz() {}
In a test file...
import * as pathFileHelpers from 'path/to/file';
pathFileHelpers.__Rewire__({
readFileSync: () => {
return 'test test test'
},
})
_get__(...).__Rewire__ is not a function
Why?
I'm working on a project that has a method defined in the script tag of the index.html file. For some reason, that causes Jest to fail when it runs.
index.html
<script>
var getCookie = function(cookieVal) { return cookieVal; }
</script>
To fix this, I've tried defining the 'getCookie' variable inside of Jest globals like:
package.json
"jest": {
"globals": {
"getCookie": "someString"
}
}
This does define getCookie, but when I run my tests I get this error:
Error in data(): "TypeError: getCookie is not a function"
which makes sense, but I'm not sure how I can define it as a function in the globals object.
How can I mock my getCookie function in Jest?
Even though the Jest docs indicate that globals cannot contain functions, I verified that global functions could still be defined with a function expression or arrow function:
{
jest: {
globals: {
getCookie() { return 'someCookie' }, // function expression
getCookie: () => 'someCookie', // arrow function
}
}
}
Alternatively, you could define a setupFiles that sets global.getCookie:
// package.json
{
jest: {
setupFiles: ['./jest.setup.js']
}
}
// jest.setup.js
global.getCookie = () => 'someCookie'
With Python it's so easy to mock a function that is used in the function under test.
# my_module.py
def function_a():
return 'a'
def function_b():
return function_a() + 'b'
# tests/test_my_module.py
from unittest import TestCase
from unittest.mock import patch
from my_module import function_b
class MyModuleTestCase(TestCase):
#patch('my_module.function_a')
def test_function_b(self, mock_function_a):
mock_function_a.return_value = 'c'
self.assertEqual(function_b(), 'cb')
Is something like this possible in JavaScript using, for example, jest?
# myModule.js
function myFunctionA() {
return 'a';
}
export function myFunctionB() {
return myFunctionA() + 'b';
}
# __test__/test.myModule.js
import { myFunctionB } from '../myModule';
describe('myModule tests', () => {
test('myFunctionB works', () => {
// Mock `myFunctionA` return value here somehow.
expect(myFunctionB()).toBe('cb')
});
});
I've read https://github.com/facebook/jest/issues/936 and still have no idea how to do it as there are so many (hacky) suggestions (some of them ~2 years old).
Jest can mock an entire module using jest.mock() or mock an individual module export using jest.spyOn() in combination with functions like mockImplementation().
This makes it easy to mock a function imported from a library:
// ---- lib.js ----
export function myFunctionA() {
return 'a';
}
// ---- myModule.js ----
import { myFunctionA } from './lib';
export function myFunctionB() {
return myFunctionA() + 'b'; // call lib.myFunctionA()
}
// ---- myModule.test.js ----
import { myFunctionB } from './myModule';
import * as lib from './lib';
describe('myModule tests', () => {
test('myFunctionB works', () => {
const mock = jest.spyOn(lib, 'myFunctionA'); // create a spy on lib.myFunctionA()
mock.mockImplementation(() => 'c'); // replace the implementation
expect(myFunctionB()).toBe('cb');
mock.mockRestore(); // remove the spy and mock implementation
});
});
In the code sample from the question myModule contains two functions and one calls the other directly.
Because a mock works on either an entire module or a module export, mocking the direct call to myFunctionA() from within myFunctionB() would be very difficult the way the code is written.
The easiest way I have found to work around situations like this is to import the module into itself and use the module when calling the function. That way it is the module export that is being called and it can be mocked in the test:
// ---- myModule.js ----
import * as myModule from './myModule';
export function myFunctionA() {
return 'a';
}
export function myFunctionB() {
return myModule.myFunctionA() + 'b'; // call myModule.myFunctionA()
}
// ---- myModule.test.js ----
import * as myModule from './myModule';
describe('myModule tests', () => {
test('myFunctionB works', () => {
const mock = jest.spyOn(myModule, 'myFunctionA'); // create a spy on myModule.myFunctionA()
mock.mockImplementation(() => 'c'); // replace the implementation
expect(myModule.myFunctionB()).toBe('cb');
mock.mockRestore(); // remove the spy and mock implementation
});
});