I am using Jest to unit test my modules. I have a module say fooModule.ts.
I have 3 functions inside export const foo = () => {}, export const bar = () => {}, export const baz = () => {}. Now the function foo() internally calls bar and baz. Now these two methods are what I want to mock to give different results to foo. How do I proceed forward with this?
I tried using mockImplementation, but later I found out that made no sense.
Related
I'm under the impression that jest.spyOn.mockImplementationOnce can mock a function as long as it is implemented as a function expression, but might fail to mock when the function is written as a function declaration. Why is it behaving like that?
I have one TS file in the folder */this_works with the following code:
export function myFunction() {
return myOtherFunction();
}
export const myOtherFunction = function() {
return 'something';
};
And then another TS file in the folder */this_doesnt with the following code:
export function myFunction() {
return myOtherFunction();
}
export function myOtherFunction() {
return 'something';
}
The only difference between them is that myOtherFunction is either a function declaration or a function expression.
Both files are submitted to the same test with jest.
import * as myModule from '../index';
describe('myFunction', () => {
it('does something', () => {
jest
.spyOn(myModule, 'myOtherFunction')
.mockImplementationOnce(
function() {
return 'hello jest';
},
);
const result = myModule.myFunction();
expect(result).toEqual('hello jest');
});
});
All code can be found at my playground repo's folder
The result is that the function expression is mocked and the test passes, while the function declaration is not mocked and the test fails.
Anecdotally, this seems to only happen if the function being mocked is not being called directly, instead it is being called by another function. When the declared function gets called directly, the test passes.
I would like to understand why that is so I can write better tests.
How can we do callback on success and failue cases for below lines of code for test coverage using jest
const handleService = () => {
window.domain.service("1321",'',onSuccess, onFailure)
}
const onSuccess = () => {
....update state values
}
const onFailure = () => {
....update state values
}
Something like this:
Spy on window.domain.service to gain access to the calls it receives. This will allow you to access the parameters of those calls which will be "1321",'',onSuccess, onFailure
Assign the function you wish to test to a variable
Invoke the function to execute the code in it (this will get you the coverage)
(Optional) assert that the callback functions behave correctly
Here is a snippet to help demonstrate
it('should run', () => {
// Some setup to create the function on the window, may not be needed if done elsewhere.
// Could be good to do this in a beforeEach and clean up in afterEach to avoid contaminating the window object
window.domain = {
service: () => {},
}
// Spy on the window.domain.service method.
// Provide a mock implementation if you don't want the real one to be called
const serviceSpy = jest.spyOn(window.domain, 'service');
executeYourCode();
// capture the arguments to the call
const [_arg1, _arg2, onSuccess, onFailure] = serviceSpy.mock.calls[0];
// execute the callbacks
onSuccess();
onFailure();
});
I am trying to export a function in a .js file using both normal or arrow function. But I don't understand which is recommended.
Export normal function
module.exports = function(id) {
console.log(id);
};
Export an arrow function
const test = id => {
console.log(id);
}
module.exports = test;
Below are few questions I have in my mind.
If normal function is recommended over an arrow function, then why I
am not recommended to use arrow function.
If arrow function is recommended over normal function, then why I am not recommended to use normal function.
How can I understand the recommended one, especially in this scenario of exporting a function?
These two snippets aren't identical. First snippet results in anonymous function, while second snippet results in named function, require('...').name === 'test' (this may be useful for debugging).
A more suitable comparison is
module.exports = function test(id) {
console.log(id);
};
vs
const test = id => {
console.log(id);
}
module.exports = test;
There's no difference between these arrow and regular function in such case because they don't use features that are specific to them (e.g. this context).
Anonymous arrow function takes less characters to type but this benefit disappears when there's a need to give a function a name via temporary test variable. They also may result in lesser memory footprint, though this concern can be ignored because the difference is negligible.
Also, named arrow functions can result in more verbose output than regular functions definitions if they are transpiled to ES5:
const test = () => {}
is transpiled to
var test = function test() {}
While it could be:
function test() {}
This isn't a concern for Node.js or other ES6 environment.
TL;DR: if a function needs to have a name for debugging or other purposes, it makes sense to use:
module.exports = function test(id) {
console.log(id);
};
If a function doesn't need a name, it's:
module.exports = id => {
console.log(id);
};
This is true for functions that don't use features specific to these function types.
const App = () => console.log("This is an app.");
export default App;
OR
export const App = () => console.log("This is an app.");
I can't figure out a way to stub a function called from within the same module this function is defined (the stub does not seem to work). Here's an example:
myModule.js:
'use strict'
function foo () {
return 'foo'
}
exports.foo = foo
function bar () {
return foo()
}
exports.bar = bar
myModule.test.js:
'use strict'
const chai = require('chai')
const sinon = require('sinon')
chai.should()
const myModule = require('./myModule')
describe('myModule', () => {
describe('bar', () => {
it('should return foo', () => {
myModule.bar().should.equal('foo') // succeeds
})
describe('when stubbed', () => {
before(() => {
sinon.stub(myModule, 'foo').returns('foo2') // this stub seems ignored
})
it('should return foo2', () => {
myModule.bar().should.equal('foo2') // fails
})
})
})
})
This reminds me of Java static functions which are not stubbable (almost).
Any idea how to achieve what I'm trying to do? I know that extracting foo in a different module will work, but that's not what I'm trying to do here. I'm also aware that invoking foo in the bar method with the keyword this will also work, I'm puzzled toward the use of ̀this in this context (since I'm not using OOP).
I just tested this. And it works like charm.
'use strict'
function foo () {
return 'foo';
}
exports.foo = foo;
function bar () {
return exports.foo(); // <--- notice
}
exports.bar = bar;
Explanation
when you do sinon.stub(myModule, 'foo').returns('foo2') then sinon stubs the exported object's foo not the actually foo function from inside your myModule.js ... as you must know, foo is in accessible from outside the module. So when you set exports.foo, the exported object exports.foo stores the ref of foo. and when you call sinon.stub(myModule, 'foo').returns('foo2'), sinon will stub exports.foo and not the actual foo
Hope this makes sense!
I was a bit wary of using exports since it's a bit magical (for instance when you're coding in Typescript, you never use it directly), so I'd like to propose an alternate solution, which still requires modifying the source code unfortunately, and which is simply to wrap the function to be stubbed into an object:
export const fooWrapper = {
foo() {...}
}
function bar () {
return fooWrapper.foo()
}
And sinon.stub(fooWrapper, 'foo'). It's a bit a shame having to wrap like that only for testing, but at least it's explicit and type safe in Typescript (contrary to to exports which is typed any).
I'm just getting into unit testing for the first time. Using Mocha in Node as the testing framework. All the examples I've come across create variables inside the it(). Does it matter if they are created inside or outside of it()? For example, if I have multiple it()s inside a describe(), and I need the same mocked data across all of the it()s. I'd rather not re-create the same variable repeatedly, if possible.
describe ('MyClass', function () {
let myObj = new MyObj // Mock data here
it ('Should be...', function () {
....
})
it ('Should be...', function () {
....
})
...
})
It's totally acceptable to have variables live outside of your individual it blocks, but it may not be appropriate depending on your use case.
For objects that you do not expect to change, Object.freeze is an option: const myObj = Object.freeze(new MyObj).
If you expect your tests to change your object, you should use beforeEach to ensure that they are restored to the proper state; this will prevent your it blocks from polluting one another and avoid an unpleasant debugging journey.
For example:
describe('MyClass', function () {
let myObj
beforEach(() => {
myObj = new MyObj()
})
it('changes myObj', () => {
changeProp(myObj.sum)
expect(myObj.sum).toEqual(4)
})
it('depends on myObj being the same', () => {
expect(myObj.sum).toEqual(2)
})
})
Alternately, you can eschew the fat arrow syntax and rely on the shared context between blocks in mocha:
beforeEach(function () {
this.myObj = new MyObj()
})
it('changes myObj', function () {
addTwo(this.myObj.sum)
expect(this.myObj.sum).toEqual(4)
})
it('depends on myObj being the same', function () {
expect(this.myObj.sum).toEqual(2)
})