Skip to content

Commit

Permalink
writing tests for middleware example changed (reduxjs#2496)
Browse files Browse the repository at this point in the history
* writing tests for middleware example changed, reduxjs#559

* note about mock impls

* backticks to single quotes

* better first test

* semi

* back ticks around `create`
  • Loading branch information
brigand authored and seantcoyote committed Jan 14, 2018
1 parent a538893 commit ad4e7b0
Showing 1 changed file with 49 additions and 34 deletions.
83 changes: 49 additions & 34 deletions docs/recipes/WritingTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,51 +403,66 @@ Middleware functions wrap behavior of `dispatch` calls in Redux, so to test this

#### Example

```js
import * as types from '../../constants/ActionTypes'
import singleDispatch from '../../middleware/singleDispatch'
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).

const createFakeStore = fakeData => ({
getState() {
return fakeData
```js
const thunk = ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState)
}
})

const dispatchWithStoreOf = (storeData, action) => {
let dispatched = null
const dispatch = singleDispatch(createFakeStore(storeData))(
actionAttempt => (dispatched = actionAttempt)
)
dispatch(action)
return dispatched
return next(action)
}
```

describe('middleware', () => {
it('should dispatch if store is empty', () => {
const action = {
type: types.ADD_TODO
}
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.

expect(dispatchWithStoreOf({}, action)).toEqual(action)
})
The invoke function runs our middleware in the same way Redux does.

it('should not dispatch if store already has type', () => {
const action = {
type: types.ADD_TODO
}
```js
const create = () => {
const store = {
getState: jest.fn(() => ({})),
dispatch: jest.fn(),
};
const next = jest.fn()

expect(
dispatchWithStoreOf(
{
[types.ADD_TODO]: 'dispatched'
},
action
)
).toNotExist()
})
const invoke = (action) => thunk(store)(next)(action)

return {store, next, invoke}
};
```

We test that our middleware is calling the `getState`, `dispatch`, and `next` functions at the right time.

```js
it(`passes through non-function action`, () => {
const { next, invoke } = create()
const action = {type: 'TEST'}
invoke(action)
expect(next).toHaveBeenCalledWith(action)
})

it('calls the function', () => {
const { invoke } = create()
const fn = jest.fn()
invoke(fn)
expect(fn).toHaveBeenCalled()
});

it('passes dispatch and getState', () => {
const { store, invoke } = create()
invoke((dispatch, getState) => {
dispatch('TEST DISPATCH')
getState();
})
expect(store.dispatch).toHaveBeenCalledWith('TEST DISPATCH')
expect(store.getState).toHaveBeenCalled()
});
```

In some cases, you will need to modify the `create` function to use different mock implementations of `getState` and `next`.

### Glossary

- [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.
Expand Down

0 comments on commit ad4e7b0

Please sign in to comment.