timkindberg / jest-when

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

Unable to match when parameter itself is a mock? #80

Open FergusMcGlynn opened 3 years ago

FergusMcGlynn commented 3 years ago

I use jest-when quite a lot, and find it incredibly useful. However, I've struggled to get it to work when the calledWith parameter is itself a mock, like in the following scenario:

import { mock } from 'jest-mock-extended';
import { mocked } from 'ts-jest/utils';
import { when } from 'jest-when';
import { NodejsFunction } from '@aws-cdk/aws-lambda-nodejs';
import { LambdaDestination } from '@aws-cdk/aws-logs-destinations';

jest.mock('@aws-cdk/aws-logs-destinations');

test('jest-when matching on a mock', () => {
    const mockLambdaDestination = mock<LambdaDestination>();
    const mockLambda = mock<NodejsFunction>();
    when(mocked(LambdaDestination)).calledWith(mockLambda).mockReturnValue(mockLambdaDestination);

    const result = new LambdaDestination(mockLambda);

    expect(result).toEqual(mockLambdaDestination);
});

The above test fails:

Error: expect(received).toEqual(expected) // deep equality

Expected: undefined
Received: {"bind": [Function bind]}

which indicates to me that jest-when has not picked up that LambdaDestination was called with the argument mockLambda and hence isn't returning the value mockLambdaDestination.

However if I re-write the test to not use jest-when and instead check that LambdaDestination was called with the expected mock value, it passes:

import { mock } from 'jest-mock-extended';
import { mocked } from 'ts-jest/utils';
import { NodejsFunction } from '@aws-cdk/aws-lambda-nodejs';
import { LambdaDestination } from '@aws-cdk/aws-logs-destinations';

jest.mock('@aws-cdk/aws-logs-destinations');

test('jest matching on a mock without help from jest-when', () => {
    const mockLambdaDestination = mock<LambdaDestination>();
    const mockLambda = mock<NodejsFunction>();
    mocked(LambdaDestination).mockReturnValue(mockLambdaDestination);

    const result = new LambdaDestination(mockLambda);

    expect(result).toEqual(mockLambdaDestination);
    expect(LambdaDestination).toHaveBeenCalledWith(mockLambda);
});

So it appears that jest is able to work out that LambdaDestination was called with mockLambda, but that jest-when is not able to.

These examples use mock from jest-mock-extended and mocked from ts-jest. I could try to come up with examples that don't use these libraries if that would help.

timkindberg commented 2 years ago

Looks like jest-mocked-extended has some built-in support for calledWith behavior as well. Have you tried that?

timkindberg commented 2 years ago

It would help if you could remove the extra libraries from your example.

joebowbeer commented 2 years ago

Related to #89 ?