0

I'm trying to test some very simple functionality with Flux store that on specific event call to service that make http request and return Promise, store looks like:

case UserActions.FETCH_USER_BY_ID:
   const userService = new UserService();
   userService.fetchUserById(action.id)
      then(user => {
        this.user = user;
        this.emit(USER_FETCH_COMPLETED);
      });

For the testing I'm using Jasmine, and my test case looks like:

it('should fetch user by id', () => {
  const userStore = require('../stores/userStore');
  const mockUser = {name: 'test', id: 123};
  spyOn(UserService.prototype, 'fetchUserById')
    .and.returnValue(Promise.resolve(mockUser));
  dispatchEvent();
  expect(userStore.user).toEqual(mockUser);
})

As expected this test if failed, because of asynchronous behavior of Promise, I'm understand the problem here but I'm can not find solution how to say to test wait until Promise from userService resolved.

zooblin
  • 2,172
  • 2
  • 27
  • 33

1 Answers1

1

I would not recommend using async calls inside the store. It can lead to an unpredictable state of the store. And probably you may have this error: Flux Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.

Instead, your userService should handleAction with the user data, once the user fetched. And your store should update then the user data.

For example,

User service:

userService.fetchUserById = function(userId) {
  apiCall(userId).then(user => handleAction(UserActions.FETCH_USER_BY_ID, user));
}

User store:

   case UserActions.FETCH_USER_BY_ID:
     this.user = payload.data;
     this.emit(USER_FETCH_COMPLETED);
     break;

Here is a good short article about fetching data with API and Flux: https://medium.com/@tribou/flux-getting-data-from-an-api-b73b6478c015#.vei6eq5gt

Then, you can write tests separately for your stores and services:

Store Test:

it('should fetch user by id', () => {
  const userStore = require('../stores/userStore');
  const mockUser = {name: 'test', id: 123};
  handleAction(UserActions.FETCH_USER_BY_ID, mockUser) 
  expect(userStore.user).toEqual(mockUser);
})

Service Test:

it('should fetch user by id', (done) => {
  const userService = require('../service/userService');
  // userService.fetchUserById(userId);
  // here you can add spyOn http service that you are using in the service
  // and mock the response from that service
  // and then validate that `handleAction` has been triggered
})
Community
  • 1
  • 1
alunyov
  • 943
  • 1
  • 10
  • 14