Skip to content

Commit 3fcca32

Browse files
JakobJingleheimerAugustinMauroyavivkeller
authored
fixup: apply suggestions from code review
Co-authored-by: Augustin Mauroy <[email protected]> Co-authored-by: Aviv Keller <[email protected]> Signed-off-by: Jacob Smith <[email protected]>
1 parent 5059c1b commit 3fcca32

File tree

1 file changed

+14
-16
lines changed

1 file changed

+14
-16
lines changed

apps/site/pages/en/learn/test-runner/mocking.md

+14-16
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ But first, there are several types of tests:
2121
| integration | components fitting together | - | external code, external system |
2222
| end-to-end (e2e) | app + external data stores, delivery, etc | A fake user (ex a Playwright agent) literally using an app connected to real external systems. | none (do not mock) |
2323

24-
There are varying schools of thought about when you should and should not mock, the broadstrokes of which are laid out below.
24+
There are different schools of thought about when to mock and when not to mock, the broad strokes of which are outlined below.
2525

2626
## When and not to mock
2727

2828
There are 3 main mock candidates:
2929

30-
- own code
31-
- external code
32-
- external system
30+
- Own code
31+
- External code
32+
- External system
3333

3434
### Own code
3535

36-
This is what you/your project control.
36+
This is what your project controls.
3737

3838
```mjs displayName="your-project/main.mjs"
3939
import foo from './foo.mjs';
@@ -53,11 +53,11 @@ For a true unit test of `main`, `foo` should be mocked: you're testing that `mai
5353

5454
Mocking `foo` can be more trouble than worth, especially when `foo` is simple, well-tested, and rarely updated.
5555

56-
Others argue that not mocking `foo` is better because it's more authentic and increases coverage of `foo` (because `main`'s tests will also verify `foo`). This can, however, create noise: when `foo` breaks, a bunch of other tests will also break, so tracking down the problem is more tedious: if only the 1 test for the item ultimately responsible for the issue is failing, that's very easy to spot; whereas 100 tests failing creates a needle-in-a-haystack to find the real problem.
56+
Not mocking `foo` can be better because it's more authentic and increases coverage of `foo` (because `main`'s tests will also verify `foo`). This can, however, create noise: when `foo` breaks, a bunch of other tests will also break, so tracking down the problem is more tedious: if only the 1 test for the item ultimately responsible for the issue is failing, that's very easy to spot; whereas 100 tests failing creates a needle-in-a-haystack to find the real problem.
5757

5858
### External code
5959

60-
This is what you/your project does not control.
60+
This is what your project does not control.
6161

6262
```mjs displayName="your-project/main.mjs"
6363
import bar from 'bar';
@@ -73,11 +73,11 @@ Uncontroversially, for unit tests, this should always be mocked. For component a
7373

7474
#### Why
7575

76-
Verifying that someone else's code works with your code is not the role of a unit test (and their code should already be tested).
76+
Verifying that code that your project does not maintain works is not the goal of a unit test (and that code should have its own tests).
7777

7878
#### Why not
7979

80-
Sometimes, it's just not realistic to mock. For example, you would almost never mock react (the medicine would be worse than the ailment).
80+
Sometimes, it's just not realistic to mock. For example, you would almost never mock a large framework such as react or angular (the medicine would be worse than the ailment).
8181

8282
### External system
8383

@@ -118,7 +118,7 @@ describe('storage', { concurrency: true }, () => {
118118

119119
const results = await read('a', true);
120120

121-
assert.equal(items.length, 1); // ensure read did not retrieve erroneous item
121+
assert.equal(results.length, 1); // ensure read did not retrieve erroneous item
122122

123123
assert.deepEqual(results[0], { key: 'good', val: 'item' });
124124
});
@@ -135,13 +135,13 @@ describe('storage', { concurrency: true }, () => {
135135
});
136136
```
137137

138-
In the above, the first and second cases (the `it`s) can sabotage each other because they are run concurrently and mutate the same store (a race condition): "save"'s insertion can cause the otherwise valid "read"'s test to fail its assertion on items found (and "read"'s can do the same thing to "save"'s).
138+
In the above, the first and second cases (the `it()` statements) can sabotage each other because they are run concurrently and mutate the same store (a race condition): `save()`'s insertion can cause the otherwise valid `read()`'s test to fail its assertion on items found (and `read()`'s can do the same thing to `save()`'s).
139139

140140
## What to mock
141141

142142
### Modules + units
143143

144-
This leverages [`mock`](https://nodejs.org/api/test.html#class-mocktracker) from node's test runner.
144+
This leverages [`mock`](https://nodejs.org/api/test.html#class-mocktracker) from the Node.js test runner.
145145

146146
```mjs
147147
import assert from 'node:assert/strict';
@@ -167,8 +167,6 @@ describe('foo', { concurrency: true }, () => {
167167

168168
// This MUST be a dynamic import because that is the only way to ensure the
169169
// import starts after the mock has been set up.
170-
// There is a far more technical explanation,
171-
// but just trust that this is logically necessary.
172170
({ foo } = await import('./foo.mjs'));
173171
});
174172

@@ -182,7 +180,7 @@ describe('foo', { concurrency: true }, () => {
182180

183181
### APIs
184182

185-
A little-known fact: node has a builtin way to mock `fetch`. [`undici`](https://github.com/nodejs/undici) is the Node.js implementation of `fetch`. You do not have to install it—it's shipped with `node` by default.
183+
A little-known fact is that there is a builtin way to mock `fetch`. [`undici`](https://github.com/nodejs/undici) is the Node.js implementation of `fetch`. You do not have to install it—it's shipped with `node` by default.
186184

187185
```mjs displayName="endpoints.spec.mjs"
188186
import assert from 'node:assert/strict';
@@ -246,7 +244,7 @@ describe('endpoints', { concurrency: true }, () => {
246244

247245
### Time
248246

249-
Like Doctor Strange, you too can control time. You would usually do this just for convience to avoid artificially protracted test runs (do you really want to wait 3 minutes for that setTimeout to trigger?). You may also want to travel through time. This leverages [`mock timers`](https://nodejs.org/api/test.html#class-mocktimers) from node's test runner.
247+
Like Doctor Strange, you too can control time. You would usually do this just for convenience to avoid artificially protracted test runs (do you really want to wait 3 minutes for that `setTimeout()` to trigger?). You may also want to travel through time. This leverages [`mock.timers`](https://nodejs.org/api/test.html#class-mocktimers) from the Node.js test runner.
250248

251249
Note the use of time-zone here (`Z` in the time-stamps). Neglecting to include a consistent time-zone can (read: likely will) lead to unexpected restults.
252250

0 commit comments

Comments
 (0)