How to mock/replace getter function of object with Jest?
JavascriptReactjsMockingSinonJestjsJavascript Problem Overview
In Sinon I can do the following:
var myObj = {
prop: 'foo'
};
sinon.stub(myObj, 'prop').get(function getterFn() {
return 'bar';
});
myObj.prop; // 'bar'
But how can I do the same with Jest?
I can't just overwrite the function with something like jest.fn()
, because it won't replace the getter
> "can't set the value of get"
Javascript Solutions
Solution 1 - Javascript
For anyone else stumbling across this answer, Jest 22.1.0 introduced the ability to spy on getter and setter methods.
Edit: like in scieslak's answer below, because you can spy on getter and setter methods, you can use Jest mocks with them, just like with any other function:
class MyClass {
get something() {
return 'foo'
}
}
jest.spyOn(MyClass, 'something', 'get').mockReturnValue('bar')
const something = new MyClass().something
expect(something).toEqual('bar')
Solution 2 - Javascript
You could use Object.defineProperty
Object.defineProperty(myObj, 'prop', {
get: jest.fn(() => 'bar'),
set: jest.fn()
});
Solution 3 - Javascript
If you care about spying only, go for @Franey 's answer. However if you actually need to stub a value for the getter, this is how you can do it:
class Awesomeness {
get isAwesome() {
return true
}
}
describe('Awesomeness', () => {
it('is not always awesome', () => {
const awesomeness = new Awesomeness
jest.spyOn(awesomeness, 'isAwesome', 'get').mockReturnValue(false)
expect(awesomeness.isAwesome).toEqual(false)
})
})
Solution 4 - Javascript
In my unity test case, as it is expected to mock external dependencies, following the thomaux's answer, i had to use a real instance instead of a mocked one in beforeEach function, see the snippet bellow.
//declaration of MyExternalConfigService with getter
@Injectable()
export class MyExternalConfigService {
constructor(private readonly configService: ConfigService) {}
get myProp():string {
return this.configService.get<string>('context.myProp')
}
}
//beforeEach unit test configuration
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
MyServiceToBeTested,
{
provide: MyExternalConfigService,
useValue: new MyExternalConfigService(new ConfigService())
}
]
}).compile()
service = module.get<MyServiceToBeTested>(
MyServiceToBeTested
)
configService = module.get<MyExternalConfigService>MyExternalConfigService)
})
//mocking a value to your test case
it('my test case', ()=>{
jest
.spyOn(configService, 'myProp', 'get')
.mockImplementationOnce(() => 'mockedValue')
...
)