Reputation: 4956
I have an utility function that exposes a generator:
export class Utility {
// provides a generator that streams 2^n binary combinations for n variables
public static *binaryCombinationGenerator(numVars: number): IterableIterator<boolean[]> {
for (let i = 0; i < Math.pow(2, numVars); i++) {
const c = [];
//fill up c
yield c;
}
}
}
Now, I am using this generator in my code as follows:
myFuncion(input){
const n = numberOfVariables(input);
const binaryCombinations = Utility.binaryCombinationGenerator(n);
let combination: boolean[] = binaryCombinations.next().value;
while (till termination condition is met) {
// do something and check whether termination condition is met
combination = binaryCombinations.next().value;
}
}
In my unit tests (using Jasmine) I want to verify how many times the generator function is invoked (i.e. how many combinations are generated) before the termination. Below is what I have tried:
it("My spec", () => {
//arrange
const generatorSpy = spyOn(Utility, "binaryCombinationGenerator").and.callThrough();
//act
//assert
expect(generatorSpy).toHaveBeenCalledTimes(16); // fails with: Expected spy binaryCombinationGenerator to have been called 16 times. It was called 1 times.
});
However, this assertion fails as binaryCombinationGenerator
is indeed called once. What I actually want to spy on is the next
method of IterableIterator
.
However, I am not sure how to do that. Please suggest.
Upvotes: 0
Views: 873
Reputation: 4956
I am posting this as an answer as this is what I have done to mock the generator function. This is based on @0mpurdy's answer.
To mock the generator function, we actually need to call a fake function, which will provide different (and limited, if applicable) values for each call of next()
of the generator function.
This can be simply achieved by the following:
//arrange
const streamSpy= jasmine.createSpyObj("myGenerator", ["next", "counter"]);
streamSpy.counter = 0;
const values = [{ value: here }, { value: goes }, { value: your }, { value: limited },
{ value: values }]; // devise something else if it is an infinite stream
// call fake function each time for next
streamSpy.next.and.callFake(() => {
if (streamSpy.counter < values.length) {
streamSpy.counter++;
return values[streamSpy.counter - 1];
}
return { value: undefined }; // EOS
});
spyOn(Utility, "myGenerator").and.returnValue(streamSpy);
...
//assert
expect(streamSpy.next).toHaveBeenCalledTimes(2);
Upvotes: 0
Reputation: 3353
You could return a jasmine spy object from the Utility.binaryCombinationGenerator
method
let binaryCombinationsSpy = jasmine.createSpyObject('binaryCombinations', ['next']);
binaryCombinationsSpy.next.and.returnValues(value1, value2);
spyOn(Utility, "binaryCombinationGenerator").and.returnValue(binaryCombinationsSpy);
expect(binaryCombinationsSpy.next).toHaveBeenCalledTimes(2);
Upvotes: 1