After a lot reading, I found that people advice to mock every dependencies in a method under unit test.
Should I mock all the dependencies when unit testing?
However, I have a method that creates a list of objects (the dependencies) and uses the method these objects to alter the list. In the real-life scenario, the method is transforming data payload sent by the client into these objects. Below is the code implementation in Typescript but it just gives you an idea.
import {expect} from 'chai';
import 'mocha';
class Bar {
private val: number;
constructor(val: number) {
this.val = val;
}
isValid(): boolean {
return this.val !== 2;
}
canMergeWith(bar: Bar): boolean {
return this.val === bar.val;
}
}
class BarBuilder {
constructor() {
}
createBars(payload: number[]): Bar[] {
const bars: Bar[] = [];
payload.forEach(p => {
bars.push(new Bar(p));
});
const filtered = this.filterBars(bars);
const merged = this.mergeBars(filtered);
return merged;
}
private filterBars(bars: Bar[]): Bar[] {
return bars.filter(b => b.isValid());
}
private mergeBars(bars: Bar[]): Bar[] {
const merged: Bar[] = [];
bars.forEach((bar, i) => {
if (i > 0) {
const before = bars[i - 1];
if (!bar.canMergeWith(before)) {
merged.push(bar);
}
} else {
merged.push(bar);
}
});
return merged;
}
}
describe('BarBuilder', () => {
it('Should convert payload into valid bars', () => {
const payload = [1, 2, 3, 4, 4, 5, 5];
const barBuilder = new BarBuilder();
const bars = barBuilder.createBars(payload);
expect(bars).to.deep.equal([{val: 1}, {val: 3}, {val: 4}, {val: 5}]);
});
});
Currently, the test is passing. But it is violating the rule that I should mock every dependency in the class.
My question which one of the following should I do:
- Should I really mock the class Bar in order to comply to that rule?
If so, I find another difficulty doing that. If I mock the class Bar, how do I make the mock methods canMergeWith
and isValid
return true or false based on their input? Isn't the equivalent as re-writting the class itself?
- Should I refactor my code instead?
I was also thinking probably the problem is with my code being not testable. Before, the methods canMergeWith
and isValid
belonged to BarBuilder
. For the sake of readability, I moved them inside Bar. But now, the unit testing BarBuilder
is not trival anymore .
- Leave the test as it is despite the fact that it is violating unit testing rule.