How to mock/replace getter function of object with Jest?

JavascriptReactjsMockingSinonJestjs

Javascript 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')
  ...
)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionI_like_foxesView Question on Stackoverflow
Solution 1 - JavascriptFraneyView Answer on Stackoverflow
Solution 2 - JavascriptAlex RobertsonView Answer on Stackoverflow
Solution 3 - JavascriptscieslakView Answer on Stackoverflow
Solution 4 - JavascriptPaulo RicardoView Answer on Stackoverflow