I want to mock a function with Jest, but only if it is called with specific arguments, for example:
function sum(x, y) {
return x + y;
}
// mock sum(1, 1) to return 4
sum(1, 1) // returns 4 (mocked)
sum(1, 2) // returns 3 (not mocked)
There is a similar feature implemented in Ruby's RSpec library:
class Math
def self.sum(x, y)
return x + y
end
end
allow(Math).to receive(:sum).with(1, 1).and_return(4)
Math.sum(1, 1) # returns 4 (mocked)
Math.sum(1, 2) # returns 3 (not mocked)
What I'm trying to achieve in my tests is a better decoupling, let's say I want to test a function that relies on sum:
function sum2(x) {
return sum(x, 2);
}
// I don't want to depend on the sum implementation in my tests,
// so I would like to mock sum(1, 2) to be "anything I want",
// and so be able to test:
expect(sum2(1)).toBe("anything I want");
// If this test passes, I've the guarantee that sum2(x) is returning
// sum(x, 2), but I don't have to know what sum(x, 2) should return
I know that there is a way to implement this by doing something like:
sum = jest.fn(function (x, y) {
if (x === 1 && y === 2) {
return "anything I want";
} else {
return sum(x, y);
}
});
expect(sum2(1)).toBe("anything I want");
But it would be nice if we had some sugar function to simplify it.
Does it sounds reasonable? Do we already have this feature in Jest?
Thanks for your feedback.
I found this library that a colleague of mine wrote recently: jest-when
import { when } from 'jest-when';
const fn = jest.fn();
when(fn).calledWith(1).mockReturnValue('yay!');
const result = fn(1);
expect(result).toEqual('yay!');
Here's the library: https://github.com/timkindberg/jest-when
jest-when mentioned by STeve Shary is probably the best option.
If you don't want to install a new library, when you don't care about the original function, here's a one-line solution:
sum.mockImplementation((x, y) => x === 1 && y === 2 && "my-return-value")
I thought I needed a way to mock with arguments too, but for me, I could solve my problem by simply knowing the order of calls.
Taken from the jest documentation
const filterTestFn = jest.fn();
// Make the mock return `true` for the first call,
// and `false` for the second call
filterTestFn.mockReturnValueOnce(true).mockReturnValueOnce(false);
So in the example above, provided you know that on first pass the function should return true and on second pass it should return false, you're good to go!
No there is no way to do this in Jest yet. You could use sinons stubs for this. from the docs:
stub.withArgs(arg1[, arg2, ...]);
Stubs the method only for the
provided arguments. This is useful to be more expressive in your
assertions, where you can access the spy with the same call. It is
also useful to create a stub that can act differently in response to
different arguments.
"test should stub method differently based on arguments": function () {
var callback = sinon.stub();
callback.withArgs(42).returns(1);
callback.withArgs(1).throws("TypeError");
callback(); // No return value, no exception
callback(42); // Returns 1
callback(1); // Throws TypeError
}
import * as helper from "../helper"; //file where all functions are
jest.spyOn(helper, "function_name").mockImplementation((argument) => {
// This argument is the one passed to the function you are mocking
if (argument === "something") {
return "something"
} else {
return "something else"
}
});
This may help...
I had something similar whereby I had the same method called with different parameters requiring different returned result from the stubbed/mocked call. I've used a variable with a list of functions when I've made a call to the mocked service i take function off the top of the queue and execute function. It requires knowledge of the order of execution you are testing and doesn't really handle varying the response by argument but has allowed me to work around the restriction in jest.
var mockedQueue = [];
mockedQueue.push(() => {return 'A';})
mockedQueue.push(() => {return 'B';})
service.invoke = jest.fn(()=>{
serviceFunctionToCall = mockedQueue.shift();
return serviceFunctionToCall();
})
Related
I'm studying Javascript basics, particularly higher order functions, at the moment. I have read many articles and watched as many videos where people explain the basic definition and demonstrate the most basic construction of a higher order function. However, when I encounter an actual problem, I am lost. Here is an example (this is just for my personal study, not for a grade or for work):
Write a maybe function that, given a predicate (a function that returns a boolean value) and any other function, only calls the latter if the former returns true: maybe(x => x > 100, myFn). If the predicate returns true, the value of x should be passed to myFn. If the predicate returns false, x should be returned unchanged.
I don't understand how to pass the value of x from one function to another...
I solved this by adding a number argument to maybe, in addition to the predicate function and callback function. However, only two parameters are specified in the prompt, so I guess I'm not doing it correctly. Here is what I did:
//predicate (evaluates to a boolean)
const notZero = function(x) {
//console.log('predicate runs!');
return x !== 0;
}
//callback (does something within the main function)
const plusOne = function(x) {
//console.log('callback runs!');
return x + 1;
}
//checking if my predicate works
//test(notZero(1), true); // => test passed!
//another callback
const myFn = function(x) {
return x - 100;
}
//main function
function maybe(number, predicate, callback) {
if (predicate(number) === true) {
//console.log('predicate === true');
//console.log(callback(number));
return callback(number);
} else {
return number;
}
}
test(maybe(1, notZero, plusOne), 2);
test(maybe(0, notZero, plusOne), 0);
test(maybe(101, x => x > 100, myFn), 1);
test(maybe(99, x => x > 100, myFn), 99);
EDIT: As shared below, maybe can now take only 2 parameters (the predicate and the callback) because it now returns a function whose parameter is number. That's the idea I was looking for.
function maybe(predicate, callback) {
return function (number) {
if (predicate(number) === true) {
return callback(number);
} else {
return number;
}
}
}
It's technically impossible. x is locked out of the world in predicate's scope. There's no way you may extract it out of this function.
Apart from that, as you correctly assume in your code, we logically need to communicate x to both predicate & callback. Otherwise, what's the point of maybe at all?
Since then, your solution is one of very few possible ones.
You may "decorate" it nicer with currying. The idea is precisely identical as in your code but if you'll do so, you will be able to call the final function exactly with 2 arguments.
const setMaybeBase => x => (predicate, callback) => predicate(x) ? callback(x) : x;
// use it later this way
const maybe42 = setMaybeBase(42);
maybe42(yourFn, yourFnTwo);
This is a huge overkill unless the argument you pass to setMaybeBase is for example a complex object you are going to work with.
Alternatively, you might go wild & use a function to get the x as well.
Nevertheless, always remember that the easiest solution is the best one.
Here is a real-world example of maybe function taken straight from node.js repo:
function maybeCallback(cb) {
if (typeof cb === 'function')
return cb;
throw new ERR_INVALID_CALLBACK(cb);
}
We have the following working test example:
"use strict";
var should = require("chai").should();
var multiply = function(x, y) {
if (typeof x !== "number" || typeof y !== "number") {
throw new Error("x or y is not a number.");
}
else return x * y;
};
describe("Multiply", function() {
it("should multiply properly when passed numbers", function() {
multiply(2, 4).should.equal(8);
});
it("should throw when not passed numbers", function() {
(function() {
multiply(2, "4");
}).should.throw(Error);
});
});
There's no explanation on why the second test needs to be run with the hack
(function() {
multiply(2, "4");
}).should.throw(Error);
If you run it like
it("should throw when not passed numbers", function() {
multiply(2, "4").should.throw(Error);
});
the test fails
Multiply
✓ should multiply properly when passed numbers
1) should throw when not passed numbers
But running the function as a regular node script does fail:
Error: x or y is not a number.
at multiply (/path/test/test.js:7:11)
So I don't get why the should doesn't pick up the fact that it throws error.
What is the cause of needing to wrap this in anonymous function() { } call? Is it do to tests running asynchronously, or scope or something?
Chai is regular JavaScript, not magic. If you have an expression a().b.c() and a throws, c() can’t catch it. c can’t even run. The engine can’t even know what c is, because a didn’t return a value whose .b.c could be looked up; it threw an error instead. When you use a function, you have an object on which to look up .should, which in turn gives you an object on which to look up and call .throw.
That’s why it can’t do that, but from an API point of view, there’s nothing wrong: .should.throw is just an assertion on a function instead of a function call.
I’d also recommend using Chai’s expect, which doesn’t insert itself into Object.prototype to give the appearance of magic.
I want to better understand es6 arrow functions.
Given the following example:
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
// snip actual enhancer logic
return {
...store,
dispatch
}
}
}
Describing the above in words:
Our exported function (applyMiddleware) takes an array parameter with spread.
Then applyMiddleware returns a nameless function with a createStore parameter, which returns another nameless function this time with three parameters.
So without the arrows it would look like this:
export default function applyMiddleware(...middlewares) {
return function(createStore){
return function(reducer,preloadedState,enhancer){
//some logic
return{...store,dispatch}
}
}
}
My questions:
Am I correct?
What is the common use case/code paradigm we see here?
The answer to your first question is more or less (see my comment). The answer to your second question is that the pattern you are seeing is a combination of using a closure and currying. The original parameters to the exported function get gathered into an array called 'middlewares' that the returned functions close over (i.e. have access to). The function then can be called again with yet another parameter 'createStore' then another function is returned that can accept even more parameters. This allows one to partially apply the parameters. For a more trivial (and perhaps more easily comprehended) example, lets take a function called 'add' that adds two numbers:
let add = (x, y) => x + y;
Not very interesting. But lets break it up so it can take the first number and return a function that takes the second:
let add = x => y => x + y;
let add3 = add(3);
let seven = add3(4); // 7
This may not seem like a big win for our add function, but you started with a much more reasonable real-world example. Additionally, rather than currying manually it is possible (and desirable) to use a curry function that does it for you, many popular libraries (lodash, underscore, ramda) implement curry for you. An example using Ramda:
let add = R.curry((x, y) => x + y);
let add3 = add(3);
let five = add3(2);
let also5 = add(3, 2);
let still5 = add(3)(2); // all are equivalent.
This answer is for those who still have some doubts in double arrow functions. Lets dig deep into it.
const doubleArrowFunc = param1 => param2 => {
console.log('param1', param1);
console.log('param2', param2);
}
If you call this function
const executeFunc = doubleArrowFunc('Hello');
If you print executeFunc in console you'll get an output like this
ƒ (param2) {
console.log('param1', param1);
console.log('param2', param2);
}
Now this is like a half executed code. If you wanna execute it fully, you've to do it like this
executeFunc('World');
//And the output will be
param1 Hello
param2 World
If you want even more understanding. I can execute the same without arrow function
function doubleArrowFunc(param1) {
return function innerFunction(param2) {
console.log('param1', param1);
console.log('param2', param2);
}
}
I'm getting around to learning JavaScript - really learning JavaScript. I come from a PHP background so some JavaScript concepts are still new to me, especially asynchronous programming. This question might have already been answered many times before but I have not been able to find an answer. It might be because I don't really even know how to ask the question other than by showing an example. So here it is:
When using the deferred package from npm, I see the following example:
delayedAdd(2, 3)(function (result) {
return result * result
})(function (result) {
console.log(result); // 25
});
They refer to this as chaining and it actually works as I'm currently using this code to check when a promise is resolved or is rejected. Even though they call it chaining, it reminds me of trailing closures like in Swift.
I don't really understand what type of chaining this is since we have a function invocation and then immediately after, an anonymous function enclosed in parentheses.
So I guess I have two questions.
What pattern is this?
How does it work? This may be a loaded question but I like to know how something works so when someone asks me about this I can give them a detailed explanation.
Here is the delayedAdd function:
var delayedAdd = delay(function (a, b) {
return a + b;
}, 100);
which uses the following function:
var delay = function (fn, timeout) {
return function () {
var def = deferred(), self = this, args = arguments;
setTimeout(function () {
var value;
try {
value = fn.apply(self, args));
} catch (e) {
def.reject(e);
return;
}
def.resolve(value);
}, timeout);
return def.promise;
};
};
It's actually really easy to understand. Let's look at what's going on here when the expression is evaluated:
First the delayedAdd(2, 3) function will be called. It does some stuff and then returns. The "magic" is all about its return value which is a function. To be more precise it's a function that expects at least one argument (I'll get back to that).
Now that we evaluated delayedAdd(2, 3) to a function we get to the next part of the code, which is the opening parenthesis. Opening and closing parenthesis are of course function calls. So we're going to call the function that delayedAdd(2, 3) just returned and we're going to pass it an argument, which is what gets defined next:
That argument is yet another function (as you can see in your example). This function also takes one argument (the result of the computation) and returns it multiplied by itself.
This function that was returned by the first call to delayedAdd(2, 3) returns yet another function, which we'll call again with an argument that is another function (the next part of the chain).
So to summarize we build up a chain of functions by passing our code to whatever function delayedAdd(2, 3) returned. These functions will return other functions that we can pass our functions again.
I hope this makes the way it works somewhat clear, if not feel free to ask more.
mhlz's answer is very clear. As a supplementary, here I compose a delayedAdd for your to better understand the process
function delayedAdd(a, b) {
var sum = a + b
return function(f1) {
var result1 = f1(sum)
return function(f2) {
f2(result1)
}
}
}
Where in your example code, the function you passed as f1 is:
function (result) {
return result * result
}
and f2 is:
function (result) {
console.log(result)
}
Functions are first-class citizens in JS - that means (among others), they can take the role of actual parameters and function return values. Your code fragment maps functions to functions.
The signatures of the functions in your chained call might look like this.
delayedAdd: number -> fn // returns function type a
a: fn ( number -> number) -> fn // returns function type b
b: fn ( number -> void ) -> void // returns nothing ( guessing, cannot know from your code portion )
General setting
Of course, JS is a weakly typed language, so the listed signatures are derived from the code fragment by guessing. There is no way to know whether the code actually does what is suggested above apart from inspecting the sources.
Given that this showed up in the context of 'chaining', the signatures probably rather look like this:
delayedAdd: number x number -> fn (( fn T -> void ) -> ( fn T -> void ))
Which means that delayedAdd maps two numbers to a function x, which maps functions of arbitrary signatures to functions of the same signature as itself.
So who would do anything like this ? And why ?
Imagine the following implementation of x:
//
// x
// Collects functions of unspecified (possibly implicit) signatures for later execution.
// Illustrative purpose only, do not use in production code.
//
// Assumes
function x ( fn ) {
var fn_current;
if (this.deferred === undefined) {
this.deferred = [];
}
if (fn === undefined) {
// apply functions
while ( this.deferred.length > 0 ) {
fn_current = this.deferred.shift();
this.accumulator = fn_current(this.accumulator);
}
return this.accumulator;
}
else {
this.deferred.push ( fn );
}
return this;
}
Together with a function delayedAdd that actually returns an object of the following kind ...:
function delayedAdd ( a1, a2) {
return x ( function () { a1 + a2; } );
}
... you'll effectively register a chain of functions to be executed at some later point of time (e.g. in a callback to some event).
Notes and reminders
JS functions are JS objects
The signatures of the registered functions may actually be arbitrary. Considering them to be unified just serves to keep this exposition simpler (well ...).
Caveat
I do not know whether the outlined codeis what node.js does (but it could be ... ;-))
To be fair this pattern can be either chaining or currying(or partial application). Depending how it's implemented. Note this is a theoretical answer to provide more information about the pattern and not your specific use case.
Chaining
There is nothing special here because we can just return a function that will be called again. Functions in javascript are first class citizens
function delayedAdd(x, y) {
// In here work with x and y
return function(fn) {
// In here work with x, y and fn
return function(fn2) {
//Continue returning functions so long as you want the chain to work
}
}
}
This make it unreadable in my opinion. There is a better alternative.
function delayedAdd(x, y) {
// In here work with x and y
return {
then: function(fn) {
// In here work with x, y and fn
return {
then: function(fn2) {
//Continue returning functions so long as you want the chain to work
}
}
}
}
}
This changes the way your functions are called from
delayedAdd(..)(..)(..); // 25
is transformed to
delayedAdd().then().then()
Not only is more readable when you are passing several callback functions but allows a distinction from the next pattern called currying.
Currying
The term cames after the mathematician Haskell Curry. The definition is this
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument (partial application). It was introduced by Moses Schönfinkel and later developed by Haskell Curry.
Basically what it does is take several arguments and merge with the subsecuents and apply them to the original function passed in the first argument.
This is a generic implementation of this function taken from Stefanv's Javascript Patterns.
{Edit}
I changed my previous version of the function to one which has partial application included to make a better example. In this version you must call the function with no argument to get the value returned or you will get another partially applied function as result. This is a very basic example, a more complete one can be found on this post.
function schonfinkelize(fn) {
var slice = Array.prototype.slice,
stored_args = [],
partial = function () {
if (arguments.length === 0){
return fn.apply(null, stored_args);
} else {
stored_args = stored_args.concat(slice.call(arguments));
return partial;
}
};
return partial;
}
This are the results of the application of this function
function add(a, b, c, d, e) {
return a + b + c + d + e;
}
schonfinkelize(add)(1, 2, 3)(5, 5)(); ==> 16
Note that add (or in your case delayedAdd) can be implemented as the curying function resulting in the pattern of your example giving you this
delayedAdd(..)(..)(..); // 16
Summary
You can not reach a conclusion about the pattern just by looking at the way the functions are called. Just because you can invoke one after the other it doens't mean is chaining. It could be another pattern. That depends on the implementation of the function.
All excellent answers here, especially #mhlz and #Leo, I'd like to touch on the chaining part you've mentioned. Leo's example shows the idea of calling functions like foo()()() but only works for fixed number of callbacks. Here's an attempt to imlpement unlimited chaining:
delayedAdd = function da(a, b){
// a function was passed: call it on the result
if( typeof a == "function" ){
this.result = a( this.result )
}
else {
// the initial call with two numbers, no additional checks for clarity.
this.result = a + b;
}
// return this very function
return da;
};
Now you can chain any number of functions in () after the first call:
// define some functions:
var square = function( number ){ return number * number; }
var add10 = function( number ){ return number + 10; }
var times2 = function( number ){ return number * 2; }
var whatIs = function( number ){ console.log( number ); return number; }
// chain them all!
delayedAdd(2, 3)(square)(whatIs)(add10)(whatIs)(times2)(whatIs);
// logs 23, 35 and 70 in the console.
http://jsfiddle.net/rm9nkjt8/3/
If we expand this syntax logically we would reach something like this:
var func1 = delayedAdd(2, 3);
var func2 = function (result) {
return result * result
};
var func3 = function (result) {
console.log(result);
};
var res = func1(func2); // variable 'res' is of type 'function'
res(func3);
Assume I have a js function. From some other point in the program, I want to run its code, but not its return statement. In its place, I would like to run some other return statement that references the variables in the scope of the original function.
Is there a way to do this, other than loading up the function source, replacing the return, and using eval on the result? Minimal modification of the original is possible, though it should not affect the original's performance by adding e.g. an extra function call.
You could try something like this, but I'm not sure it meets your conditions.
Edit: Fixed to work in jsfiddle
// Modified to set all "shared" variables as "members" of the function.
var test = function() {
test.val = "one";
test.val2 = "two";
return 1;
}
// Using different result
function test2() {
test();
return test.val2;
}
Unless you're able to restructure your methods to accommodate a callback or introduce some other parameter-based logic-flow (not an option for 3rd party code), you're out of luck.
Here's a callback sample (fiddle, credit to dzejkej's answer)
function foo(callback) {
var x = 2;
// pass your values into the callback
return callback ? callback.call(this, x) : x * 2;
}
document.write(foo());
document.write("<hr/>");
// specify the parameters for your callback
document.write(foo(function(x){ return x * 4;}) );
You can introduce a callback function that will get called if available otherwise "standard" value will be returned.
function test(callback) {
// ...
return callback ? callback.call(this) : /* original value returned */ "xyz";
}
test(function() { /* "this" is same as in test() */ });
EDIT:
If you want to pass variables inside callback then you just list them in the .call() function.
Example:
function test(callback) {
var a = 4;
var b = 2;
// ...
return callback ? callback.call(this, a, b) : a * b;
}
test(); // 8
test(function(a, b) { return a + b; }); // 6
See this fiddle.
Provided that you would keep variables of the outer scope function within a single object, you could try something like the following:
function original(a, b, c, rep) {
var data = {};
// Do some fancy stuff but make sure to keep everything under data
data.a = a.replace(/foo/, 'bar');
...
if ( Object.prototype.toString.call(rep) === '[object Function]' )
return rep.call(data);
return data;
}
function replacement() {
return 'foo' + this.a;
}
// Now let's make use of both the original and the replacement ...
console.log(original('foo', x, y)); // => {a: "bar", b: ...}
console.log(original('foo', x, y, replacement)); // => {a: "foobar", b: ...}
Hope, it's what you where asking for.
cheers
I think you really misunderstand the concept of return statement. The return statement of a function will simply return a value, or an object, or undefined if there is no return parameter specified.
If all you're trying to do is execute a function but "not its return statement" than you would just invoke the function and not do anything with the returned value/object:
However, if what you mean is that you would like to execute a function but not execute the "parameter" to its return statement then that literally means to selectively execute an arbitrary portion of the body of a function. And as far as I know that is not possible (without using reflection to get the function definition, modify the definition, and then dynamically invoking the modified version - which you said you didn't want to do).