Order of calling mock.calledWith() matters
Unless I'm missing something, which is quite possible. The order in which you set up mocks with calledWith matters.
A simple example:
describe('A simple example', () => {
let mockHttpClient: MockProxy<HttpClient>;
beforeEach(() => {
mockHttpClient = mock<HttpClient>();
});
it('will return the most generic mock value if it\'s defined first', async () => {
mockHttpClient.get.calledWith(any()).mockResolvedValue('first');
mockHttpClient.get.calledWith(anyString()).mockResolvedValue('second');
mockHttpClient.get.calledWith('bar').mockResolvedValue('third');
await expect(mockHttpClient.get('foo')).resolves.toBe('second');
});
});
in the example above the mock returns 'first'. In this example it isn't that big of a deal, you could just reorder them and put the more specific ones ontop and the mock works as expected.
However, the use case where I think it becomes problematic is if you want to define the generic mockResolvedValue in a beforeEach for all tests, and then define more specific mockResolvedValues with in a specific test, this behavior will cause an issue in that scenario.
Here's an example of the more problematic use case for reference
describe('A simple example', () => {
let mockHttpClient: MockProxy<HttpClient>;
beforeEach(() => {
mockHttpClient = mock<HttpClient>();
mockHttpClient.get.calledWith(any()).mockResolvedValue('first');
});
it('will return the most generic mock value if it\'s defined first', async () => {
mockHttpClient.get.calledWith(anyString()).mockResolvedValue('second');
mockHttpClient.get.calledWith('bar').mockResolvedValue('third');
await expect(mockHttpClient.get('foo')).resolves.toBe('second');
});
});
Any insight or suggestions is appreciated. Also, love this library. It's super useful.
you can reset mock before initialized for every test
`it('will return the most generic mock value if it\'s defined first', async () => {
mockReset(mockHttpClient); // <--- reset mock conditions
mockHttpClient.get.calledWith(any()).mockResolvedValue('first'); // <--- duplicate if need
mockHttpClient.get.calledWith(anyString()).mockResolvedValue('second');
mockHttpClient.get.calledWith('bar').mockResolvedValue('third');
await expect(mockHttpClient.get('foo')).resolves.toBe('second');
});`
Maybe I'm missing something, but this kinda renders beforeEach useless in this scenario doesn't it? I had expected that calledWith would choose the most specific match based on some set of rules. Maybe that wasn't the original intent, but it seems useful.
For single test - yes, useless. In other case you can set default order and reorder them in concrete test case with mockReset(mockHttpClient)