How to Loop in Jest Unit Tests
This post contain affiliate links to Udemy courses, meaning when you click the links and make a purchase, I receive a small commission. I only recommend courses that I believe support the content, and it helps maintain the site.
Sometimes when writing Jest unit tests you are going to want to be able to loop over items to quickly test different cases. Whether this be looping over an array of items, or counting between numbers in your Jest Test. This will massively simplify your Jest test suite.
There are a number of ways to do this. This post aims to outline the ways that I have looped through Jest tests in the past.
Looping over tests with Jest.Each
For very basic repetitive Jest tests I would use jest.each
. It allows you to keep duplicating the same test with different data. You can write the test once and let the data do the work.
Using Basic Arrays and printf
An example of this is:
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
expect(a + b).toBe(expected);
});
The above code is taking in a set of data within an array, The name of the test using printf to inject parameters into the text, and the arguments to be passed into the test itself.
For more information about jest.each
take a look at the Jest documentation.
Using Array of Objects
Rather than using printf, you can pass in an array of objects and reference them using string literals. Like so:
test.each([
{a: 1, b: 1, expected: 2},
{a: 1, b: 2, expected: 3},
{a: 2, b: 1, expected: 3},
])('.add($a, $b)', ({a, b, expected}) => {
expect(a + b).toBe(expected);
});
I personally prefer this. It is more explicit in what each item is, and allows you to build a more complex test data set. It is a nice way of being able to Jest test each array of objects – and cleanly see what is expected for each item.
Using Jest.Each with a Table
The jest.each
API also lets you pass data into it in a more ‘visual’ way. Using one large string literal you can shape the data in a table.
This looks like:
test.each`
a | b | expected
${1} | ${1} | ${2}
${1} | ${2} | ${3}
${2} | ${1} | ${3}
`('returns $expected when $a is added $b', ({a, b, expected}) => {
expect(a + b).toBe(expected);
});
The first row sets up the table headings, and the rest of the rows using template literals to add the values. Then the test title itself using template literals to inject the data into the string.
Not my top choice, but some people like this way of handling the tests.
Using a For Loop in Jest Tests
The for loop is my go to when wanting to dynamically loop through Jest tests. In this way of writing loops in jest there is no need for the printf variable injection. Call me old fashioned (or wrong), but I also like the flexibility of being able to fully control the tests, and how they are created. This way of testing also makes the Jest tests portable between test frameworks, as they are not tied in with specific semantics. Another bonus is IDE support – a simple for
loop will be picked up, a jest
each is less likely to be.
The for
loop approach allows me to loop describe
jest test blocks, as well as the unit tests inside. However with this freedom comes the need to restrict yourself. Otherwise the tests could become to over-engineered and end up being too confusing.
Simple tests are better.
const testData = [
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 }
];
for (let i = 0; i < testData.length; i += 1) { it(`.add(${testData[i].a}, ${testData[i].b})`, () => {
expect(testData[i].a + testData[i].b).toBe(testData[i].expected);
});
}
The above shows how the for loop would be used to create dynamically generated Jest tests.
What About looping Jest tests with forEach?
I have asked if the same flow can be achieved putting Jest test cases in a forEach
loop. It is possible for smaller synchronous tests – however you cannot use forEach
loops with async
/await
so I wouldn’t recommend using it. You can read more about why here.
Jest test.each vs. forEach vs. for
JavaScript’s vanilla for
is the clear winner for me. It is easy to write, not tied into specific frameworks, and is easy to understand. I wouldn’t say not to use jest.each
as it has its uses for simpler tests. I would never use forEach
.
For a break down of Jest and React Testing Library take a look at this short overview.
For more Jest hints and tips take a look at the Jest Testing Category!
Hopefully this helped you, and if you have any questions you can reach me at: @robertmars