Skip to content

Commit

Permalink
feat: Add verifyAll and resetAll
Browse files Browse the repository at this point in the history
  • Loading branch information
NiGhTTraX committed Jun 27, 2020
1 parent 0e66b13 commit eef45e0
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 11 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ try {
verify(fn); // throws
```

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.

![verify error](./media/verify.png)

### Resetting expectations
Expand All @@ -235,6 +237,8 @@ reset(fn);
instance(fn)(1); // throws
```

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.

### Argument matchers

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.
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import { instance } from './instance';
import { It } from './matcher';
import { mock } from './mock';
import { reset } from './reset';
import { verify } from './verify';
import { reset, resetAll } from './reset';
import { verify, verifyAll } from './verify';
import { when } from './when';

export { mock, when, instance, verify, reset, It };
export { mock, when, instance, verify, verifyAll, reset, resetAll, It };
4 changes: 4 additions & 0 deletions src/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ export const getMockState = (mock: Mock<any>): MockState => {
export const setMockState = (mock: Mock<any>, state: MockState): void => {
mockMap.set(mock, state);
};

export const getAllMocks = (): [Mock<any>, MockState][] => {
return Array.from(mockMap.entries());
};
15 changes: 12 additions & 3 deletions src/reset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getMockState } from './map';
import { getAllMocks, getMockState } from './map';
import { Mock } from './mock';

/**
Expand All @@ -12,9 +12,18 @@ import { Mock } from './mock';
* reset(fn);
*
* instance(fn)(); // throws
* @param mock
*/
// TODO: add resetAll
export const reset = (mock: Mock<any>): void => {
getMockState(mock).repository.clear();
};

/**
* Reset all existing mocks.
*
* @see reset
*/
export const resetAll = (): void => {
getAllMocks().forEach(([mock]) => {
reset(mock);
});
};
21 changes: 19 additions & 2 deletions src/verify.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UnexpectedCalls, UnmetExpectations } from './errors';
import { ExpectationRepository } from './expectation-repository';
import { getMockState } from './map';
import { getAllMocks, getMockState } from './map';
import { Mock } from './mock';

export const verifyRepo = (repository: ExpectationRepository) => {
Expand All @@ -21,16 +21,33 @@ export const verifyRepo = (repository: ExpectationRepository) => {
/**
* Verify that all expectations on the given mock have been met.
*
* @throws Will throw if there are remaining expectations that were set
* using `when` and that weren't met.
*
* @throws Will throw if any unexpected calls happened. Normally those
* calls throw on their own, but the error might be caught by the code
* being tested.
*
* @example
* const fn = mock<() => number>();
*
* when(fn()).thenReturn(23);
*
* verify(fn); // throws
*/
// TODO: add verifyAll
export const verify = <T>(mock: Mock<T>): void => {
const { repository } = getMockState(mock);

verifyRepo(repository);
};

/**
* Verify all existing mocks.
*
* @see verify
*/
export const verifyAll = (): void => {
getAllMocks().forEach(([mock]) => {
verify(mock);
});
};
21 changes: 18 additions & 3 deletions tests/verify.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/* eslint-disable class-methods-use-this */
import { expect } from 'tdd-buffet/expect/jest';
import { describe, it } from 'tdd-buffet/suite/node';
import { instance, mock, verify } from '../src';
import { beforeEach, describe, it } from 'tdd-buffet/suite/node';
import { instance, mock, verify, when } from '../src';
import { UnexpectedCalls, UnmetExpectations } from '../src/errors';
import { Expectation } from '../src/expectation';
import { CallMap, ExpectationRepository } from '../src/expectation-repository';
import { verifyRepo } from '../src/verify';
import { resetAll } from '../src/reset';
import { verifyAll, verifyRepo } from '../src/verify';
import { NotMatchingExpectation } from './expectations';

describe('verify', () => {
Expand All @@ -21,6 +22,20 @@ describe('verify', () => {
});
});

describe('verifyAll', () => {
beforeEach(() => {});

it('should verify all mocks', () => {
resetAll();

const fn = mock<() => void>();

when(fn()).thenReturn(undefined);

expect(() => verifyAll()).toThrow(UnmetExpectations);
});
});

describe('verifyRepo', () => {
class MockRepo implements ExpectationRepository {
private readonly unmet: Expectation[] = [];
Expand Down

0 comments on commit eef45e0

Please sign in to comment.