253

I have a mapModule where I import components and export them:

import ComponentName from '../components/ComponentName';

export default {
  name: ComponentName,
};

How can I test that mapModule has the correct exported keys, values and that they are not null or undefined?

Liam
  • 27,717
  • 28
  • 128
  • 190
fasenberg
  • 2,735
  • 3
  • 10
  • 16

6 Answers6

255

you can use one of those:

toEqual and toMatchObject are template matchers for objects:

let Obj = {name: 'component name', id: 2};
expect(oneObj).toEqual({name: 'component name'}) // false, should be exactly equal all Obj keys and values  
expect(oneObj).toMatchObject({name: 'component name'}) // true

or easly use toHaveProperty :

let Obj = {name: 'component name'};
expect(oneObj).toHaveProperty('name') // true
expect(oneObj).toHaveProperty('name', 'component name') // true
Jared Dykstra
  • 3,596
  • 1
  • 13
  • 25
toufek khoury
  • 2,974
  • 2
  • 8
  • 15
240

In version 23.3.0 of jest,

expect(string).toMatch(string) 

expects a string.

Use:

const expected = { name:'component name' }
const actual = { name: 'component name', type: 'form' }
expect(actual).toMatchObject(expected)

result is passing test

user3605834
  • 2,590
  • 1
  • 12
  • 5
86

Keep in mind that .toMatchObject checks

"that a JavaScript object matches a subset of the properties of an object."

So toMatchObject can have unintended assertions such as:

expect({ a: 1, b: 2 }).toMatchObject({ a: 1 }); // pass

If you do want to match an object exactly, you should use .toStrictEqual, available since jest 23:

expect({ a: 1, b: 2 }).toStrictEqual({ a: 1 }); // fail
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
rtorres
  • 2,601
  • 3
  • 27
  • 33
  • Actually that is exactly the assertion toMatchObject is designed for. You can use toEqual if you don't want that behaviour... – Dan Oct 29 '20 at 19:40
  • 3
    This answer really should be the preferred solution for most cases. – mikemaccana Mar 09 '21 at 19:49
11

Just adding this tip, thought it gave even better granularity to my own tests, especially when matching against arguments to mocked services:

expect.objectContaining({
   url: expect.stringContaining('https://'),
})

Alternatively, you can use regex with expect.stringMatching which tests the given regex against the value. Pretty neat.

expect.stringContaining expect.stringMatching

Dylan Pierce
  • 4,313
  • 3
  • 35
  • 45
8

For a single key you can check out

expect(Boolean(obj[prop])).toBe(true | false);

For multiple key (where all must be present) you can use,

expect(Boolean(obj[prop1]) && Boolean(obj[prop2])).toBe(true | false);

For multiple key (where any one must be present) you can use

expect(Boolean(obj[prop1]) || Boolean(obj[prop2])).toBe(true | false);

Devorein
  • 1,112
  • 2
  • 15
  • 23
  • Completely incorrect. The value passed to `expect` is resolved to be a boolean, meaning you'll miss useful debug output from jest if the test ever breaks. `true | false` resolves to `1` - really, you're calling `.toBe(1)` - does that make sense? No. Do not use this approach. – Gershom Maes Aug 09 '23 at 16:41
1

Another way is to:

expect(JSON.stringify(object)).toBe(JSON.stringify(object))

This will ensure the objects are the same.

However using this:

expect(object).toMatchObject(object)

is the best option in most cases.

beeinger
  • 141
  • 1
  • 4
  • 16
    Hey pal, you should never try to compare JSON.stringify from an object, as object order is not guaranteed so the stringify version might change. – Javier Cobos Jul 20 '21 at 09:26