Using the factory pattern, i wrote snippets of code that use firebase cloud functions :
//Notice that when instantiated it does calculations and returns a value
function sumAndMultiply(int number) {
function sum(i) {
return i + 1;
}
function multiply(i) {
return i * 3;
}
const x = sum(number);
const y = multiply(x);
return y;
}
everting working fine, but, what i can make if i need to unit test multiply() or sum() function?
describe('Unit testing', () => {
it('test sum function', () => {
//How i can call sum function without call sumAndMultiply?
let result = sum(3);
expect(result == 4);
});
it('test multiply function', () => {
//How i can call multiply function without call sumAndMultiply?
let result = multiply(3);
expect(result == 9);
});
});
As I'm talking about unit testing, one idea is to avoid editing the code used for production, but changes that make the code more readable or better are accepted
The problem with your approach is that your code is tightly coupled with the implementation of sum and multiply functions. This makes testing way harder, and testing the units of sum and multiply would take a lot of effort.
One way of solving this code smell is to use Dependency Injection. This way, you would provide both the sum and multiply functions, but the interface of sumAndMultiplyfunctions would need to change. This way, your code would become:
//Notice that when instantiated it does calculations and returns a value
function sumAndMultiply(number, sum, multiply) {
const x = sum(number);
const y = multiply(x);
return y;
}
function sum(i) {
return i + 1;
}
function multiply(i) {
return i * 3;
}
That way, you INJECT these functions. Good thing is that now we can unit test both our sum and multiply functions as you've sugested. Even better, we can now mock our sum and multiply functions on sumAndMultiply.
Related
So after 3 days I've started to understand what callback function actually is and just come across this code:
const timeFuncRuntime = funcParameter => {
let t1 = 120;
funcParameter();
let t2 = 200;
return t2 - t1;
}
const addOneToOne = () => 1 + 1;
timeFuncRuntime(addOneToOne);
console.log(timeFuncRuntime(addOneToOne))
With just my 3 months experience in JS (which I'm aware is nothing), I can tell that in this line of code "timeFuncRuntime(addOneToOne);" another function is being passed as an argument which is 'addOneToOne' however, I don't understand what it's actually doing here? What's the point of having it there?
In the last line when the main function is called with another function being passed as an argument, that function (probably that's what a callback function is called) is returning 1+1 = 2 however, it's just returning and I don't think there's any need for that, or is there?
In the first arrow function, two local variables are declared with different values with a callback function (I think it's a callback) so what is that callback function doing there?
This code all appears to be useless.
The function passed is a pure function, but its result is never used, so it isn't doing anything meaningful.
The wrapper timeFuncRuntime will always return 80, which also isn't very useful.
That means this code is essentially equivalent to:
console.log(80)
Just with extra processing.
This code is likely attempting to show use of Higher Order Functions, but isn't doing so very effectively. The t2 - t1 looks like it's attempting to show how you'd write a benchmarking function, but they hardcoded in numbers which defeats the purpose.
Study functions like map and reduce to get better examples of why you'd want to pass functions around.
What they were likely going for is something like this:
const benchmark = (f) => {
let t1 = Date.now();
f();
let t2 = Date.now();
return t2 - t1;
}
Then you can do:
let t = benchmark(() => {
// Something expensive
for(let i = 0; i < 100000; i++) {
let d = new Date()
}
});
// Prints how long it took the function to execute.
// A number around 50 for me.
console.log(t);
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);
}
I'm trying to solve this algorithm. I think I'm very close.
I need the seven function to pass the a variable to the timesFive function. OR is there a way I can pass the * 5 operation from timesFive to seven in order to get the desired result?
I'm not allowed to have variables outside of these two function scopes.
I can add another argument to timesFive as long as b remains the first argument.
function seven(action) {
var a = 7;
return action;
}
function timesFive(b) {
console.log(a); // How can I access "a"?
return a * 5;
}
console.log(seven(timesFive())); // Desired result: 35
timeFive should return a function and seven should expect a function as a parameter. Then seven can simply call the function that timesFive() returns (so basically returning the * 5 operation as you mentioned in your question):
function seven(action) {
var a = 7;
return action(a);
}
function timesFive() {
return (a) => a * 5;
}
console.log(seven(timesFive())); // Desired result: 35
BTW
You'll often see these kind of exercises written in a way that mimics the functional notation from math, like:
const seven = (action) => action(7);
const timesFive = () => (a) => a * 5;
console.log(seven(timesFive())); // Desired result: 35
I am using Mocha with Sinon and attempting to test a recursive call (fibonacci). My code is:
'use strict';
let sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect;
chai.use(require('sinon-chai'));
let fib = function (n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
return fib(n-2) + fib(n-1);
}
};
describe('fib', function() {
it('should repeat calculations', function() {
let originalFib = fib;
fib = sinon.spy(fib)
expect(fib(6)).to.equal(8);
expect(fib).to.have.callCount(25);
fib = originalFib;
});
});
This code works as-is, however, if I replace the line:
let fib = function (n) {
with:
const fib = function (n) {
I get the following error:
TypeError: Assignment to constant variable.
This is as expected, but it raises the question, how would I test a recursive function that was declared const using Sinon?
Edited Jasmine has something called .callThrough() which seems to allow testing of recursive function.
It seems to me there is no way to replicate this behavior with Sinon? I have looked at the following bug reports / feature requests:
https://github.com/sinonjs/sinon/issues/668
https://github.com/sinonjs/sinon/issues/989
Thank you.
Calling sinon.spy directly on a function creates a wrapper around the original function that tracks calls and returned values but does not modify it, so you do not need to remember it and restore it.
With that information, the obvious answer would be to simply name your spy something else:
describe('fib', function() {
it('should repeat calculations', function() {
const spy = sinon.spy(fib);
expect(spy(6)).to.equal(8);
expect(spy).to.have.callCount(25);
});
});
This approach works fine for non-recursive functions, but as you might notice, while the first assertion passes, the second fails with only 1 call having been made to spy.
The problem is that there is one more issue at play here. The function fib calls itself directly and those direct recursive calls are not tracked by wrapping the function with sinon.spy.
More details on this issue as well as the corresponding solution is presented in the answer here.
The main issue when you changed the code into const fib = function(n) is because you have this subsequent code fib = sinon.spy(fib). We can't redeclare assignment for any variable with const.
For this kind of test, based on my experience, I feel that using spy is not necessary unless you have other function to call inside fib. We can just execute and check the value for all possible cases.
'use strict';
const sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect;
chai.use(require('sinon-chai'));
const fib = function (n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
return fib(n - 2) + fib(n - 1);
}
};
describe('fib', function () {
it('should repeat calculations', function () {
expect(fib(0)).to.equal(0); // add more cases
expect(fib(1)).to.equal(1);
expect(fib(6)).to.equal(8);
});
});
Hope it helps.
Is there a way to keep some sort of internal state while writing a curried function?
For example, let's say I want to write a curried function that takes into account the number of times the function was called previously.
I.e. addProgressively(3)(4)(5) = 1*3 + 2*4 + 3*5 = 26.
My approach is to add some counter that increments every time a new curried function is returned but I can't find a good way to keep track of that argument within the addProgressively function.
You could use another variable as closure for the factor.
function addProgressively(x) {
var factor = 1,
sum = factor * x;
function f(y) {
factor++;
sum += factor * y;
return f;
};
f.toString = function () { return sum; };
return f;
}
console.log(addProgressively(3)(4)(5));