Reputation: 1234
I have a class in which i use strategy pattern it looks something like this:
class Foo {
constructor() {
this.doStuff = function() { /* not used really */ }
}
create(config) {
this.type = config.type;
// assign other variables to this
this.doStuff = StuffStrategy(config.type);
this.doStuff();
}
}
StuffStrategy is a function that returns other functions which use this
context differently based on type.
function StuffStrategy(type) {
switch(type) {
case A: return StrategyA;
case B: return StrategyB;
// ...
}
}
function StrategyA() {
if(this.someVarInFoo) {
return 'a thing'
} else
return 'a different thing' + this.otherVarInFoo
}
I assign particular Strategy function inside create method.
Then I would like to test the create
method if it calls doStuff
.
describe('how create method works', () => {
const instance = new Foo();
const spy = jest.spyOn(instance, 'doStuff');
instance.create(config);
expect(spy).toBeCalled();
});
But when I try to make spy before calling instance.create then it refers to default method assigned in constructor, which gets replaced inside create.
If i make spy after calling instance.create then it will not pick the call
.
I tried to add .bind
when defining this.doStuff:
this.doStuff = StuffStrategy(config.type).bind(this);
but it does not work either.
Is there something wrong with my setup? How can I make this test case work?
Upvotes: 1
Views: 278
Reputation: 124
You have to spyOn the strategy methods of your Foo class. So for every config.type you check then which strategy method has been called.
export class Foo {
constructor(){
this.doStuff = null;
}
create(config){
this.type = config.type;
// assign other variables to this
this.doStuff = StuffStrategy(config.type);
this.doStuff();
}
strategyA(){...}
strategyB(){...}
StuffStrategy(configtype) {
switch (configtype) {
case "A": return this.strategyA;
case "B": return this.strategyB;
}
}
}
import { Foo } from 'anyPlaceFoo/foo';
describe('Strategy', () => {
it('should call strategy A', () => {
const foo = new Foo();
// here you can spy on every strategy method.
jest.spyOn(foo, 'strategyA');
jest.spyOn(foo, 'strategyB');
foo.create({ type: 'A' });
// check if the selected one has been called but not the others
expect(foo.strategyA).toHaveBeenCalled();
expect(foo.strategyB).not.toHaveBeenCalled();
})
})
Upvotes: 1