Skip to content

Commit eef45e0

Browse files
committed
feat: Add verifyAll and resetAll
1 parent 0e66b13 commit eef45e0

6 files changed

Lines changed: 60 additions & 11 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ try {
219219
verify(fn); // throws
220220
```
221221

222+
It is recommended that that you call `verify()` on your mocks at the end of every test. This will make sure you don't have any unused expectations in your tests and that your code hasn't silently caught any of the errors that are thrown when an unexpected call happens. You can use `verifyAll()` to check all existing mocks e.g. in an `afterEach` hook.
223+
222224
![verify error](./media/verify.png)
223225

224226
### Resetting expectations
@@ -235,6 +237,8 @@ reset(fn);
235237
instance(fn)(1); // throws
236238
```
237239

240+
If you create common mocks that are shared by multiple tests you should reset them before using them e.g. in a `beforeEach` hook. You can use `resetAll()` to reset all existing mocks.
241+
238242
### Argument matchers
239243

240244
Sometimes you're not interested in specifying all the arguments in an expectation. Maybe they've been covered in another test, maybe they're hard to specify e.g. callbacks. In those cases you can use argument matchers to either ignore some arguments or use custom matchers to check them.

src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import { instance } from './instance';
33
import { It } from './matcher';
44
import { mock } from './mock';
5-
import { reset } from './reset';
6-
import { verify } from './verify';
5+
import { reset, resetAll } from './reset';
6+
import { verify, verifyAll } from './verify';
77
import { when } from './when';
88

9-
export { mock, when, instance, verify, reset, It };
9+
export { mock, when, instance, verify, verifyAll, reset, resetAll, It };

src/map.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,7 @@ export const getMockState = (mock: Mock<any>): MockState => {
5656
export const setMockState = (mock: Mock<any>, state: MockState): void => {
5757
mockMap.set(mock, state);
5858
};
59+
60+
export const getAllMocks = (): [Mock<any>, MockState][] => {
61+
return Array.from(mockMap.entries());
62+
};

src/reset.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getMockState } from './map';
1+
import { getAllMocks, getMockState } from './map';
22
import { Mock } from './mock';
33

44
/**
@@ -12,9 +12,18 @@ import { Mock } from './mock';
1212
* reset(fn);
1313
*
1414
* instance(fn)(); // throws
15-
* @param mock
1615
*/
17-
// TODO: add resetAll
1816
export const reset = (mock: Mock<any>): void => {
1917
getMockState(mock).repository.clear();
2018
};
19+
20+
/**
21+
* Reset all existing mocks.
22+
*
23+
* @see reset
24+
*/
25+
export const resetAll = (): void => {
26+
getAllMocks().forEach(([mock]) => {
27+
reset(mock);
28+
});
29+
};

src/verify.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { UnexpectedCalls, UnmetExpectations } from './errors';
22
import { ExpectationRepository } from './expectation-repository';
3-
import { getMockState } from './map';
3+
import { getAllMocks, getMockState } from './map';
44
import { Mock } from './mock';
55

66
export const verifyRepo = (repository: ExpectationRepository) => {
@@ -21,16 +21,33 @@ export const verifyRepo = (repository: ExpectationRepository) => {
2121
/**
2222
* Verify that all expectations on the given mock have been met.
2323
*
24+
* @throws Will throw if there are remaining expectations that were set
25+
* using `when` and that weren't met.
26+
*
27+
* @throws Will throw if any unexpected calls happened. Normally those
28+
* calls throw on their own, but the error might be caught by the code
29+
* being tested.
30+
*
2431
* @example
2532
* const fn = mock<() => number>();
2633
*
2734
* when(fn()).thenReturn(23);
2835
*
2936
* verify(fn); // throws
3037
*/
31-
// TODO: add verifyAll
3238
export const verify = <T>(mock: Mock<T>): void => {
3339
const { repository } = getMockState(mock);
3440

3541
verifyRepo(repository);
3642
};
43+
44+
/**
45+
* Verify all existing mocks.
46+
*
47+
* @see verify
48+
*/
49+
export const verifyAll = (): void => {
50+
getAllMocks().forEach(([mock]) => {
51+
verify(mock);
52+
});
53+
};

tests/verify.spec.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/* eslint-disable class-methods-use-this */
22
import { expect } from 'tdd-buffet/expect/jest';
3-
import { describe, it } from 'tdd-buffet/suite/node';
4-
import { instance, mock, verify } from '../src';
3+
import { beforeEach, describe, it } from 'tdd-buffet/suite/node';
4+
import { instance, mock, verify, when } from '../src';
55
import { UnexpectedCalls, UnmetExpectations } from '../src/errors';
66
import { Expectation } from '../src/expectation';
77
import { CallMap, ExpectationRepository } from '../src/expectation-repository';
8-
import { verifyRepo } from '../src/verify';
8+
import { resetAll } from '../src/reset';
9+
import { verifyAll, verifyRepo } from '../src/verify';
910
import { NotMatchingExpectation } from './expectations';
1011

1112
describe('verify', () => {
@@ -21,6 +22,20 @@ describe('verify', () => {
2122
});
2223
});
2324

25+
describe('verifyAll', () => {
26+
beforeEach(() => {});
27+
28+
it('should verify all mocks', () => {
29+
resetAll();
30+
31+
const fn = mock<() => void>();
32+
33+
when(fn()).thenReturn(undefined);
34+
35+
expect(() => verifyAll()).toThrow(UnmetExpectations);
36+
});
37+
});
38+
2439
describe('verifyRepo', () => {
2540
class MockRepo implements ExpectationRepository {
2641
private readonly unmet: Expectation[] = [];

0 commit comments

Comments
 (0)