timkindberg / jest-when

Jest support for mock argument-matched return values.
MIT License
734 stars 38 forks source link

Allow setting default after training #59

Closed narthur closed 2 years ago

narthur commented 3 years ago

Would it be possible to make it so that you could set or replace the default return value without also resetting previously-added training? Basically, could jest-when be modified to make the following test pass?

it('can add default after training, reduced', async () => {
  const fn = jest.fn();

  when(fn).calledWith(1).mockReturnValue('a');

  fn.mockReturnValue('b');

  expect(fn(1)).toEqual('a');
  expect(fn(2)).toEqual('b');
});
timkindberg commented 2 years ago

Sorry after looking at this more closely this is not possible. Or at least not with the fn.mockReturnValue('b') coming after the when usage.

By declaring mockReturnValue it essentially clobbers the whole internal mockImplementation that jest-when sets up for you. The same thing would happen in regular jest, this is basically what's happening.

const fn = jest.fn()

fn.mockImplementation((num) => {
  if (num === 1) return 'a'
})
fn.mockReturnValue('b') // This will just win no matter what

expect(fn(1)).toEqual('a') // fails and will still return 'b' (as before my change)
expect(fn(2)).toEqual('b')

However, good news I spent a little time and now you can do this at least if you upgrade to version 3.4.0

const fn = jest.fn()

when(fn).calledWith(1).mockReturnValue('a')
when(fn).mockReturnValue('b') // Just have to wrap with when()

expect(fn(1)).toEqual('a')
expect(fn(2)).toEqual('b')
narthur commented 2 years ago

@timkindberg Wow, this is great! Thank you for making this improvement, and for the great library.