Skip to content

Commit b8cf8aa

Browse files
brigandtimdorr
authored andcommitted
writing tests for middleware example changed (#2496)
* writing tests for middleware example changed, #559 * note about mock impls * backticks to single quotes * better first test * semi * back ticks around `create`
1 parent 7c68f34 commit b8cf8aa

File tree

1 file changed

+49
-34
lines changed

1 file changed

+49
-34
lines changed

docs/recipes/WritingTests.md

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -403,51 +403,66 @@ Middleware functions wrap behavior of `dispatch` calls in Redux, so to test this
403403

404404
#### Example
405405

406-
```js
407-
import * as types from '../../constants/ActionTypes'
408-
import singleDispatch from '../../middleware/singleDispatch'
406+
First, we'll need a middleware function. This is similar to the real [redux-thunk](https://github.com/gaearon/redux-thunk/blob/master/src/index.js).
409407

410-
const createFakeStore = fakeData => ({
411-
getState() {
412-
return fakeData
408+
```js
409+
const thunk = ({ dispatch, getState }) => next => action => {
410+
if (typeof action === 'function') {
411+
return action(dispatch, getState)
413412
}
414-
})
415413

416-
const dispatchWithStoreOf = (storeData, action) => {
417-
let dispatched = null
418-
const dispatch = singleDispatch(createFakeStore(storeData))(
419-
actionAttempt => (dispatched = actionAttempt)
420-
)
421-
dispatch(action)
422-
return dispatched
414+
return next(action)
423415
}
416+
```
424417

425-
describe('middleware', () => {
426-
it('should dispatch if store is empty', () => {
427-
const action = {
428-
type: types.ADD_TODO
429-
}
418+
We need to create a fake `getState`, `dispatch`, and `next` functions. We use `jest.fn()` to create stubs, but with other test frameworks you would likely use sinon.
430419

431-
expect(dispatchWithStoreOf({}, action)).toEqual(action)
432-
})
420+
The invoke function runs our middleware in the same way Redux does.
433421

434-
it('should not dispatch if store already has type', () => {
435-
const action = {
436-
type: types.ADD_TODO
437-
}
422+
```js
423+
const create = () => {
424+
const store = {
425+
getState: jest.fn(() => ({})),
426+
dispatch: jest.fn(),
427+
};
428+
const next = jest.fn()
438429

439-
expect(
440-
dispatchWithStoreOf(
441-
{
442-
[types.ADD_TODO]: 'dispatched'
443-
},
444-
action
445-
)
446-
).toNotExist()
447-
})
430+
const invoke = (action) => thunk(store)(next)(action)
431+
432+
return {store, next, invoke}
433+
};
434+
```
435+
436+
We test that our middleware is calling the `getState`, `dispatch`, and `next` functions at the right time.
437+
438+
```js
439+
it(`passes through non-function action`, () => {
440+
const { next, invoke } = create()
441+
const action = {type: 'TEST'}
442+
invoke(action)
443+
expect(next).toHaveBeenCalledWith(action)
448444
})
445+
446+
it('calls the function', () => {
447+
const { invoke } = create()
448+
const fn = jest.fn()
449+
invoke(fn)
450+
expect(fn).toHaveBeenCalled()
451+
});
452+
453+
it('passes dispatch and getState', () => {
454+
const { store, invoke } = create()
455+
invoke((dispatch, getState) => {
456+
dispatch('TEST DISPATCH')
457+
getState();
458+
})
459+
expect(store.dispatch).toHaveBeenCalledWith('TEST DISPATCH')
460+
expect(store.getState).toHaveBeenCalled()
461+
});
449462
```
450463

464+
In some cases, you will need to modify the `create` function to use different mock implementations of `getState` and `next`.
465+
451466
### Glossary
452467

453468
- [Enzyme](http://airbnb.io/enzyme/): Enzyme is a JavaScript Testing utility for React that makes it easier to assert, manipulate, and traverse your React Components' output.

0 commit comments

Comments
 (0)