-
Notifications
You must be signed in to change notification settings - Fork 469
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(dependencies): Added explicit dependencies option to createEpicM…
…iddleware (#193) https://redux-observable.js.org/docs/recipes/InjectingDependenciesIntoEpics.html Closes #163
- Loading branch information
Showing
7 changed files
with
179 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# Injecting Dependencies Into Epics | ||
|
||
Injecting your dependencies into your Epics can help with testing. | ||
|
||
Let's say you want to interact with the network. You could use the `ajax` helpers directly from `rxjs`: | ||
|
||
```js | ||
import { ajax } from 'rxjs/observable/dom/ajax'; | ||
|
||
const fetchUserEpic = (action$, store) => | ||
action$.ofType('FETCH_USER') | ||
.mergeMap(({ payload }) => | ||
ajax.getJSON(`/api/users/${payload}`) | ||
.map(response => ({ | ||
type: 'FETCH_USER_FULFILLED', | ||
payload: response | ||
})) | ||
); | ||
``` | ||
|
||
But there is a problem with this approach: Your file containing the epic imports its dependency directly, so mocking it is much more difficult. | ||
|
||
One approach might be to mock `window.XMLHttpRequest`, but this is a lot more work and now you're not just testing your Epic, you're testing that RxJS correctly uses XMLHttpRequest a certain way when in fact that shouldn't be the goal of your test. | ||
|
||
### Injecting dependencies | ||
|
||
To inject dependencies you can use `createEpicMiddleware`'s `dependencies` configuration option: | ||
|
||
```js | ||
import { createEpicMiddleware, combineEpics } from 'redux-observable'; | ||
import { ajax } from 'rxjs/observable/dom/ajax'; | ||
import rootEpic from './somewhere'; | ||
|
||
const epicMiddleware = createEpicMiddleware(rootEpic, { | ||
dependencies: { getJSON: ajax.getJSON } | ||
}); | ||
``` | ||
|
||
Anything you provide will then be passed as the third argument to all your Epics, after the store. | ||
|
||
Now your Epic can use the injected `getJSON`, instead of importing it itself: | ||
|
||
```js | ||
// Notice the third argument is our injected dependencies! | ||
const fetchUserEpic = (action$, store, { getJSON }) => | ||
action$.ofType('FETCH_USER') | ||
.mergeMap(() => | ||
getJSON(`/api/users/${payload}`) | ||
.map(response => ({ | ||
type: 'FETCH_USER_FULFILLED', | ||
payload: response | ||
})) | ||
); | ||
|
||
``` | ||
|
||
To test, you can just call your Epic directly, passing in a mock for `getJSON`: | ||
|
||
```js | ||
import { ActionsObservable } from 'redux-observable'; | ||
import { fetchUserEpic } from './somewhere/fetchUserEpic'; | ||
|
||
const mockResponse = { name: 'Bilbo Baggins' }; | ||
const action$ = ActionsObservable.of({ type: 'FETCH_USERS_REQUESTED' }); | ||
const store = null; // not needed for this epic | ||
const dependencies = { | ||
getJSON: url => Observable.of(mockResponse) | ||
}; | ||
|
||
// Adapt this example to your test framework and specific use cases | ||
fetchUserEpic(action$, store, dependencies) | ||
.toArray() // buffers all emitted actions until your Epic naturally completes() | ||
.subscribe(actions => { | ||
assertDeepEqual(actions, [{ | ||
type: 'FETCH_USER_FULFILLED', | ||
payload: mockResponse | ||
}]); | ||
}); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters