There are several popular ways to write asserts. Besides calling functions, people also like to use matchers, which bear certain similarities to a mini-language to write checks.
Matchers became popular in test frameworks after the emergence of BDD) (Behaviour Driven Development). Technically, this approach tends to make tests look like a natural language description of the task at hand. This makes it possible to use them as documentation for people who can't read program code (anyway, in practice, it's a bit more complicated). Matchers have replaced the usual function statements in many languages:
// Checking reference equality
// assert.equal([1, 2], [1, 2])
expect([1, 2]).toBe([1, 2]); // false
// Checking value equality
// assert.deepEqual([1, 2], [1, 2])
expect([1, 2]).toEqual([1, 2]); // true
Any matcher in Jest starts with the expect(data)
function, which takes the data for checking. Then, expect()
returns a special object, on which you can call various matchers to check. Jest has dozens of matchers for a wide variety of situations. Their number is so large since developers want to have the most accurate possible account of why what happened.
Let's imagine a function that returns an array, and we want to check its size. To do this, you can use the toBe
matcher:
const data = [1, 2, 3];
// take takes the first n elements
// assert.equal(take(data, 2).length, 2)
expect(take(data, 1).length).toBe(2);
This matcher will do the job just fine. But if an error occurs, the output is not very informative:
expect(received).toBe(expected) // Object.is equality
Expected: 2
Received: 1
Therefore, it's better to take a specialized matcher to check the size of the array:
expect(take(data, 1)).toHaveLength(2);
Then the output will tell us much more:
expect(received).toHaveLength(expected)
Expected length: 2
Received length: 1
Received array: [1]
Because expect
passes the array itself, not its length, Jest can output the contents of the array if an error occurs. This, again, makes debugging easier.
Below are some popular matchers that are useful in everyday testing:
expect(null).toBeNull();
// Checks a value to see if it is truthy (a truthy value is any value that is considered to be true)
expect(true).toBeTruthy();
// Exact comparison with true
expect(true).toBe(true);
expect(undefined).toBeUndefined();
// Check if an array contains an element
expect([1, 2, 3]).toContain(2);
// Checking if a string contains a substring
expect('hello, world').toMatch('hello');
// Checks if an object has a property with a certain value
expect({ key: 'value' }).toHaveProperty('key', 'value');
In addition, you can apply the not
modifier to any matcher, which will invert the matcher's behavior:
expect(null).not.toBeNull(); // not null
expect(undefined).not.toBeUndefined(); // not undefined
expect([1, 2, 3]).not.toContain(2); // not contain 2
expect('hello, world').not.toMatch('hello'); // not match hello
https://repl.it/@hexlet/js-testing-matchers-expect-en#index.test.js
The toMatchObject
matcher is particularly worth noting. It's used when we're not interested in the whole object, only part of it:
const user = {
firstName: 'john',
lastName: 'smith',
age: '33',
};
// the test is successful, since only firstName is checked
expect(user).toMatchObject({ firstName: 'john' });
These aren't all the matchmakers that Jest has. Moreover, Jest is flexible enough to allow you to add more matchers. You can find libraries with matchers for different situations on GitHub.
In general, you'll have to keep looking at the documentation to remember what's there. Otherwise, it might come down to using to Equal()
only. Perhaps this is the main disadvantage of using matchers: you need to remember them and apply them correctly.
Recommended materials
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.