Home How to test redux-thunk middleware async functions?
Reply: 2

How to test redux-thunk middleware async functions?

Amit Kaspi
1#
Amit Kaspi Published in 2016-01-18 18:15:22Z

I'm trying to test my asyn thunk middleware function using mocha, chai and sinon (my first time!).

Please consider my files:

ayncActionCreators.js

export const fetchCurrentUser = () => {
   return (dispatch) => {
      setTimeout(dispatch, 100);
   }
};

ayncActionCreators.spec.js

//...
it('Should work', () => {
   const dispatch = sinon.spy();
   const action = fetchCurrentUser();

   action(dispatch);

   expect(dispatch.called).to.be.true;
});

I did not yet implement the fetchCurrentUser function - just assumed it will take some "server" time and then it will call 'dispatch()'.

The spec fails, due to the async flow. If I add a setTimeout of 101 ms before the expect - it passes.

My code will use some DB API that returns promise, so the async function will eventually look like:

//...
return (dispatch) => {
   return dbAPI.fetchUser().then(dispatch(....));
}

So I tried to require dbAPI and create a sinon.stub().returns(Promise.resolve()) inside the test and it didn't work as well (I thought that since the stub returns a resolved promise - the async function will act like a synchronous function).

Any ideas how should I test async functions like that?

Thank, Amit.

Amit Kaspi
2#
Amit Kaspi Reply to 2016-01-18 18:56:25Z

Well, I think I've found a solution:

Assuming my async function looks like this:

//...
return (dispatch) => {
   return dbAPI.fetchUser().then(dispatch(....));
}

Then I can write the spec as follows:

it('Should work', () => {
   dbAPI.fetchUser = sinon.stub().returns(Promise.resolve({username: 'John'}));

   const dispatch = sinon.spy();
   const action = fetchCurrentUser();

   action(dispatch).then(() => {
      expect(dispatch.called).to.be.true;
   });
});

I don't know if this is a workaround or not, but it works. I would appreciate your opinions of a better way of doing this...

Thanks, Amit.

El Yobo
3#
El Yobo Reply to 2017-04-06 05:38:25Z

Don't mock dispatch with sinon, write your own and call Mocha's done() in that when it's done.

it('Should work', (done) => {
   const dispatch = () => {
     // Do your tests here
     done();
   };
   const action = fetchCurrentUser();

   action(dispatch)
     // Also allow quick failures if your promise fails
     .catch(done);
})

If you're just wanting to ensure that the dispatch is called, then mocha will time out. The catch on the returned promise from your async action creator allows errors to be shown in the right place and for the test to fail rather than time out.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.305246 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO