timkindberg / jest-when

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

Keep default implementation when attaching to an existing mock #78

Closed undsoft closed 2 years ago

undsoft commented 3 years ago
const test = jest.fn((yes: boolean): string => (yes ? 'pizza' : 'pasta'));
when(test).calledWith(true).mockReturnValueOnce('Luigi');

console.log(test(true));
console.log(test(false));

// Actual:
// Luigi
// undefined

// Expected
// Luigi
// pasta

Rationale: I have a factory in one place of a system that returns a method that is already mocked in certain way. What I was specifically looking for is a convenient way of adding another condition to this mock in a different part of the system.

I understand that I can rewrite my original test declaration using jest-when, but the current behaviour of overriding existing implementations seems intrusive.

The syntax of when().calledWith() itself implies behaviour that only happens under specific conditions.

timkindberg commented 3 years ago

Seems legit. I'd accept a PR for this behavior. If I get time I think it would be easy.

Asafkbalink commented 3 years ago

Yes. I was debugging it for a few hours to get to this conclusion, I'm pretty surprised this is not the default behavior. If we are mocking the return value once, it shouldn't affect the base mock value. Anyway, good to see it being acknowledged.

We use this simple workaround for now:

afterEach(() => {
  resetAllWhenMocks();
});
materkel commented 3 years ago

This also affects spyOn - I expect the default implementation to be called when not matched (instead of undefined)

  const fn = val => val + 5;
  const obj = { fn };
  const spy = jest.spyOn(obj, 'fn');
  when(spy).calledWith(1).mockReturnValue(42);

  expect(obj.fn(1)).toBe(42);
  expect(obj.fn(2)).toBe(7); // actual undefined