In our team of JavaScript devs we have embraced redux/react style of writing pure functional code. However, we do seem to have trouble unit testing our code. Consider the following example:
function foo(data) {
return process({
value: extractBar(data.prop1),
otherValue: extractBaz(data.prop2.someOtherProp)
});
}
This function call depends on calls to process
, extractBar
and extractBaz
, each of which can call other functions. Together, they might require a non-trivial mock for data
parameter to be constructed for testing.
Should we accept the necessity of crafting such a mock object and actually do so in tests, we quickly find we have test cases that are hard to read and maintain. Furthermore, it very likely leads to testing the same thing over and over, as unit tests for process
, extractBar
and extractBaz
should probably also be written. Testing for each possible edge case implemented by these functions via to foo
interface is unwieldy.
We have a few solutions in mind, but don't really like any, as neither seems like a pattern we have previously seen.
Solution 1:
function foo(data, deps = defaultDeps) {
return deps.process({
value: deps.extractBar(data.prop1),
otherValue: deps.extractBaz(data.prop2.someOtherProp)
});
}
Solution 2:
function foo(
data,
processImpl = process,
extractBarImpl = extractBar,
extractBazImpl = extractBaz
) {
return process({
value: extractBar(data.prop1),
otherValue: extractBaz(data.prop2.someOtherProp)
});
}
Solution 2 pollutes foo
method signature very quickly as the number of dependent function calls rises.
Solution 3:
Just accept the fact that foo
is a complicated compound operation and test it as a whole. All the drawbacks apply.
Please, suggest other possibilities. I imagine this is a problem that the functional programming community must have solved in one way or another.