DEV Community

Luka Zmikic Engels
Luka Zmikic Engels

Posted on

1

Partially matching object, array and function with Jest

JestJs πŸƒ Delightful JavaScript Testing

It is really delightful as the team states! For the last couple of years that is accompanying me in my daily struggles, it has shown it's worth. One of the best parts is the partial match on object, array and function, which will be the focus of this blog post.

Partially matching objects

Let's say you need to test a unit that changes just parts of an object. It is indifferent of the remaining parts of the object. Your unit test should check just the changes the unit influences.

In the code block below, a simple fixture containing some nested objects and arrays, which will be used in the following examples:

const resultFixtureObject = {
 active: true,
 id: 'e0e0e0e0-2b79-4eba-ab39-b2dfdb2f0eba',
 firstName: 'Jester',
 lastName: 'Magic',
 finances: {
  incomes: [
  {
    type: 'salary',
    amount: 150000,
    currency: '$',
   },
   {
    type: 'dividend',
    amount: 6000,
    currency: '$',
   },
   {
    type: 'rent',
    amount: 12000,
    currency: '$',
   },
  ],
 },
};
Enter fullscreen mode Exit fullscreen mode

Match object

In the test below, the expected result object must match a few properties:

expect(resultFixtureObject).toEqual(
 expect.objectContaining({
   active: true,
   id: 'e0e0e0e0-2b79-4eba-ab39-b2dfdb2f0eba',
   firstName: 'Jester',
   lastName: 'Magic',
 })
);
Enter fullscreen mode Exit fullscreen mode

Match nested object

You can match nested objects by simply nesting objectContaining() expectations. In this case, expecting object finances that must have nested object incomes. We do not care about the content of the incomes, in this unit test:

expect(resultFixtureObject).toEqual(
 expect.objectContaining({
  finances: expect.objectContaining({ 
   incomes: expect.anything()
  })
 })
);
Enter fullscreen mode Exit fullscreen mode

Partially matching arrays

Just as the objects, there is a way to partially match arrays. You can expect single or multiple item matches on an array.
Expecting one item to match:

expect(resultFixtureObject).toEqual(
 expect.objectContaining({
  finances: expect.objectContaining({
   incomes: expect.arrayContaining([
    {
     type: 'rent',
     amount: 12000,
     currency: '$',
    },
   ]),
  }),
 })
);
Enter fullscreen mode Exit fullscreen mode

or multiple, complete or partial matches:

expect(resultFixtureObject).toEqual(
 expect.objectContaining({
  finances: expect.objectContaining({
   incomes: expect.arrayContaining([
    {
     type: 'rent',
     amount: 12000,
     currency: '$',
    },
    expect.objectContaining({
     type: 'salary',
    }),
   ]),
  }),
 })
);
Enter fullscreen mode Exit fullscreen mode

Partially matching function parameter calls

Aforementioned operations can be applied to toHaveBeenCalledWith() matcher as well.
Below a variant with toHaveBeenNthCalledWith() matcher. Verifying just the third call to the function:

const functionMock = jest.fn();
functionMock('string arg');
functionMock(['array arg']);
functionMock(resultFixtureObject);

expect(functionMock).toHaveBeenNthCalledWith(
 3,
 expect.objectContaining({
  finances: expect.objectContaining({
   incomes: expect.arrayContaining([
    expect.objectContaining({
     type: 'rent',
    }),
    expect.objectContaining({
     type: 'salary',
    }),
   ]),
  }),
 })
);
Enter fullscreen mode Exit fullscreen mode

Complete test file with comments inside

describe('Jest Expect Partial Match', () => {
const resultFixtureObject = {
active: true,
id: 'e0e0e0e0-2b79-4eba-ab39-b2dfdb2f0eba',
firstName: 'Jester',
lastName: 'Magic',
finances: {
incomes: [
{
type: 'salary',
amount: 150000,
currency: '$',
},
{
type: 'dividend',
amount: 6000,
currency: '$',
},
{
type: 'rent',
amount: 12000,
currency: '$',
},
],
},
};
it('should expect partial match on object', async () => {
//partial match
expect(resultFixtureObject).toEqual(
expect.objectContaining({
active: true,
id: 'e0e0e0e0-2b79-4eba-ab39-b2dfdb2f0eba',
firstName: 'Jester',
lastName: 'Magic',
})
);
//nested object match
expect(resultFixtureObject).toEqual(
expect.objectContaining({
finances: expect.objectContaining({
incomes: expect.anything()
}),
})
);
//partial match
//match finances object contains incomes object/array
//incomes array contains specific item
expect(resultFixtureObject).toEqual(
expect.objectContaining({
finances: expect.objectContaining({
incomes: expect.arrayContaining([
{
type: 'rent',
amount: 12000,
currency: '$',
},
]),
}),
})
);
//partial match
//match finances object contains incomes object/array
//incomes array contains item rent and partial item where type is salary
expect(resultFixtureObject).toEqual(
expect.objectContaining({
finances: expect.objectContaining({
incomes: expect.arrayContaining([
{
type: 'rent',
amount: 12000,
currency: '$',
},
expect.objectContaining({
type: 'salary',
}),
]),
}),
})
);
});
it('should expect function to be called with', async () => {
const functionMock = jest.fn();
functionMock('string arg');
functionMock(['array arg']);
functionMock(resultFixtureObject);
//third call to the function was made with object
//array contains objects with 'rent' and 'salary' types
expect(functionMock).toHaveBeenNthCalledWith(
3,
expect.objectContaining({
finances: expect.objectContaining({
incomes: expect.arrayContaining([
expect.objectContaining({
type: 'rent',
}),
expect.objectContaining({
type: 'salary',
}),
]),
}),
})
);
});
});

Tiugo image

Fast, Lean, and Fully Extensible

CKEditor 5 is built for developers who value flexibility and speed. Pick the features that matter, drop the ones that don’t and enjoy a high-performance WYSIWYG that fits into your workflow

Start now

Top comments (0)

Sentry image

Make it make sense

Make sense of fixing your code with straight-forward application monitoring.

Start debugging β†’

πŸ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay