Jest partial matching on objects, arrays and functions

12 March 2021
·
jest

Sometimes with Jest, you only need to test part of an object exists, or test on a subset of an array. We can do this using Jest’s partial matchers.

In this post I will cover:

  • Using Jest’s objectContaining to match on certain key/value pairs in objects
  • Using Jest’s arrayContaining to match on certain values in arrays
  • How to use partial matching with Jest’s toHaveBeenCalledWith

Object partial matching with Jest’s objectContaining

When you want to test the subset of an object, or a specific key/value pair, you can use the objectContaining matcher.

test('should contain important value in object', () => {
    const object = {
        important: 'important',        ignore: 'ignore',
    };
        
    expect(object).toEqual(expect.objectContaining({
        important: 'important'
    }));
d});

This test will pass as long as the object contains important: 'important'.

Nested object partial matching

If you are looking for a value in a nested object, you can also nest objectContaining.

test('should contain important value in nested object', () => {
    const nestedObject = {
        ignore: 'ignore',
        payload: {
           important: 'important',           ignore: 'ignore',
        },
    };

    expect(nestedObject).toEqual(
        expect.objectContaining({
            payload: expect.objectContaining({
                important: 'important',
            }),
        })
    );
});

Array partial matching with Jest’s arrayContaining

As well as objects, you might only care about certain values in an array. In this case, you can use arrayContaining for partial matching on arrays.

test('should contain important value in array', () => {
    const array = [
        'ignore', 
        'important'    ];

    expect(array).toEqual(expect.arrayContaining(['important']))
});

This test will pass as long as the array contains the string 'important'.

Match an array in any order (unordered array)

The arrayContaining matcher will also work regardless of the order of your array.

test('should contain important values in array, in any order', () => {
    const array = [
        'ignore', 
        'important',        'alsoImportant',        'veryImportant',        'veryVeryImportant',    ];

    expect(array).toEqual(expect.arrayContaining(
        ['veryVeryImportant', 'veryImportant', 'alsoImportant', 'important']
    ));
});

If you wanted to make sure that the array contained values in any order, but didn’t contain any other values, you could assert that the length of the array is as expected.

test('should contain only the important values in array, in any order', () => {
    const array = [
        'important',        'alsoImportant',        'veryImportant',    ];

    expect(array).toEqual(expect.arrayContaining(
        ['veryImportant', 'alsoImportant', 'important']
    ));
	expect(array).toHaveLength(3);
});

Partial matching objects in an array

With an array of objects, we can use a combination of Jest’s arrayContaining and objectContaining. This will let you assert on a specific object in an array (and even a specific value inside of that object).

test('should contain important objects in array', () => {
    const array = [
        { 
            important: 'important',            ignore: 'ignore'
        },
        {
            ignore: 'ignore',
        }
    ];

    expect(array).toEqual(expect.arrayContaining(
        [expect.objectContaining({ important: 'important' })]
    ));
});

Matching on arguments in function calls with Jest’s toHaveBeenCalledWith

We use toHaveBeenCalledWith when we want to assert that a function was called with a specific set of arguments. If you only care about a specific argument in a function call, you can replace the other arguments with expect.anything().

test('should have been called with specific argument', () => {
    const mockFunction = jest.fn();

    mockFunction('ignore', 'ignore', 'important');

    expect(mockFunction).toHaveBeenCalledWith(
        expect.anything(), expect.anything(), 'important'
    );
});

If you want to be a bit more specific, you can also use expect.any() if you want to specify the type of the other arguments, such as a String or Object.

mockFunction({ignore: 'ignore'}, 'ignore', 'important');

expect(mockFunction).toHaveBeenCalledWith(
    expect.any(Object), expect.any(String), 'important'
);

Comments