Imagine that you have following situation: your calls to external api are using helper modules where all request logic lies. For instance, you have
backendService
:
exportconstmakeRequest=async()=>return fetch.get('http://www.some_api.com');
In your epic you use this as follows:
import*as backendService from'./backendService'constfetchBackendServiceEpic=(action$, store)=>
action$
.filter(isActionOf(YOUR_TRIGGER_ACTION)).switchMap(action=> Observable.from(backendService.makeRequest())).mapTo(YOUR_SUCCESS_ACTION).catch(err=> Observable.of(YOUR_ERROR_ACTION))
Everything seems fine but to test this epic you have to mock whole API request to http://www.some_api.com
using for instance nock . Your test starts to get a little bit heavy to write:
describe('fetchBackendServiceEpic',()=>{
it.should('fetch service',()=>{const mockStore =configureMockStore()nock(`http://www.some_api.com`).get().reply(200,{})returnrootEpic(ActionsObservable.from(YOUR_TRIGGER_ACTION), mockStore).toArray().toPromise().then(actions=>{expect(actions).toEqual([YOUR_TRIGGER_ACTION,YOUR_SUCCESS_ACTION])})})})
Can you do better?
Yes, using dependency injection. Your epic is depended on backendService
. How can you inject it to your epic? The actual way of doing this is in the documentation : Injecting Dependencies Into Epics · redux-observable. Thanks to that you have your epic with dependency injected:
constfetchBackendServiceEpic=(action$, store,{ makeRequest })=>
action$
.filter(isActionOf(YOUR_TRIGGER_ACTION)).switchMap(action=> Observable.from(backendService.makeRequest())).mapTo(YOUR_SUCCESS_ACTION).catch(err=> Observable.of(YOUR_ERROR_ACTION))
To test it you need:
describe('fetchBackendServiceEpic',()=>{
it.should('fetch service',()=>{const dependencies ={ makeRequest: jest.fn().mockReturnValue([{}])}fetchBackendServiceEpic(YOUR_TRIGGER_ACTION,(store =null), dependencies).toArray().subscribe(actions=>{expect(actions).toEqual([YOUR_TRIGGER_ACTIONS,YOUR_SUCCESS_ACTION])})})})
As you see here there is just injecting dependency with your desired return value - you are testing just logic of your epics and if proper actions are dispatched of your TRIGGER_ACTION
.
Summary
As you can see dependency injection in epics can be a powerful way to ease your testing of epics.