-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: runnable example of the for Each test #13428
Changes from 8 commits
65cfe82
6f43205
3a88b69
38afc48
8ef4867
9398746
4753f97
01bf339
5ae1f95
ebc6112
544a9c7
05cca48
5bd950f
c98ed64
1222c5d
988db29
2414a55
2f7efae
f467915
9aaa5dd
6cf4e4a
f1cae77
b1eac2c
817d3cd
11aed76
9b893b2
408dc62
f75b8a4
e01bb92
25dbb66
3658f8c
77be83a
b0d31c1
737fb4d
0d91ee2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,41 +17,49 @@ function forEach(items, callback) { | |
callback(items[index]); | ||
} | ||
} | ||
module.exports = forEach; | ||
``` | ||
|
||
To test this function, we can use a mock function, and inspect the mock's state to ensure the callback is invoked as expected. | ||
|
||
```javascript | ||
```js title="foreach.test.js" | ||
Jeroendevr marked this conversation as resolved.
Show resolved
Hide resolved
Jeroendevr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const forEach = require('./foreach'); | ||
|
||
const mockCallback = jest.fn(x => 42 + x); | ||
forEach([0, 1], mockCallback); | ||
|
||
// The mock function is called twice | ||
expect(mockCallback.mock.calls.length).toBe(2); | ||
test('forEach mock function', () => { | ||
Jeroendevr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
forEach([0, 1], mockCallback); | ||
|
||
// The first argument of the first call to the function was 0 | ||
expect(mockCallback.mock.calls[0][0]).toBe(0); | ||
// The mock function was called twice | ||
expect(mockCallback.mock.calls).toHaveLength(2); | ||
Jeroendevr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// The first argument of the second call to the function was 1 | ||
expect(mockCallback.mock.calls[1][0]).toBe(1); | ||
// The first argument of the first call to the function was 0 | ||
expect(mockCallback.mock.calls[0][0]).toBe(0); | ||
|
||
// The return value of the first call to the function was 42 | ||
expect(mockCallback.mock.results[0].value).toBe(42); | ||
``` | ||
// The first argument of the second call to the function was 1 | ||
expect(mockCallback.mock.calls[1][0]).toBe(1); | ||
|
||
// The return value of the first call to the function was 42 | ||
expect(mockCallback.mock.results[0].value).toBe(42); | ||
} | ||
) | ||
``` | ||
## `.mock` property | ||
|
||
All mock functions have this special `.mock` property, which is where data about how the function has been called and what the function returned is kept. The `.mock` property also tracks the value of `this` for each call, so it is possible to inspect this as well: | ||
|
||
```javascript | ||
const myMock = jest.fn(); | ||
const myMock1 = jest.fn(); | ||
const a = new myMock1(); | ||
console.log(myMock1.mock.instances); | ||
// > [ <a> ] | ||
|
||
const a = new myMock(); | ||
const myMock2 = jest.fn(); | ||
const b = {}; | ||
const bound = myMock.bind(b); | ||
const bound = myMock2.bind(b); | ||
bound(); | ||
|
||
console.log(myMock.mock.instances); | ||
// > [ <a>, <b> ] | ||
console.log(myMock2.mock.contexts); | ||
// > [ <b> ] | ||
``` | ||
|
||
These mock members are very useful in tests to assert how these functions get called, instantiated, or what they returned: | ||
|
@@ -69,12 +77,18 @@ expect(someMockFunction.mock.calls[0][1]).toBe('second arg'); | |
// The return value of the first call to the function was 'return value' | ||
expect(someMockFunction.mock.results[0].value).toBe('return value'); | ||
|
||
// The function was called with a certain `this` context: the `element` object. | ||
expect(someMockFunction.mock.contexts[0]).toBe(element); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm.. I guess these are accidental changes. Jest v25 does not have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah my bad. Glad you paid good attention to it. |
||
// This function was instantiated exactly twice | ||
expect(someMockFunction.mock.instances.length).toBe(2); | ||
|
||
// The object returned by the first instantiation of this function | ||
// had a `name` property whose value was set to 'test' | ||
expect(someMockFunction.mock.instances[0].name).toBe('test'); | ||
|
||
// The first argument of the last call to the function was 'test' | ||
expect(someMockFunction.mock.lastCall[0]).toBe('test'); | ||
``` | ||
|
||
## Mock Return Values | ||
|
@@ -105,8 +119,8 @@ const result = [11, 12].filter(num => filterTestFn(num)); | |
|
||
console.log(result); | ||
// > [11] | ||
console.log(filterTestFn.mock.calls); | ||
// > [ [11], [12] ] | ||
console.log(filterTestFn.mock.calls[0][0]); // 11 | ||
console.log(filterTestFn.mock.calls[1][0]); // 12 | ||
``` | ||
|
||
Most real-world examples actually involve getting ahold of a mock function on a dependent component and configuring that, but the technique is the same. In these cases, try to avoid the temptation to implement logic inside of any function that's not directly being tested. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thought. What about using ESM syntax here? The examples below written in ESM: https://jestjs.io/docs/next/mock-functions#mocking-modules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ESM syntax is then
export forEach;
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is:
And instead of
const forEach = require('./foreach');
:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I thought there were two ways to export a module.
One as you describe it. Add
export
before the function declaration and one where you can group all the functions, classes you want to export together (for example at the bottom)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok if v25 is acceptable I'll change the others as well. Thanks for learning on the job.