mercredi 2 décembre 2020

Enzyme integration testing of redux saga - call to axios api failing/not executed and no feed-back given

I am trying to setup tests for some an action creator that is triggering a redux saga.

My saga retrieves a word from a local flask server (will always return the same word) and then displays that word. This is not my real-life case but I tried to start with something easy...

My action creator and saga work as expected when I trigger them with a button in my react app (the word is retrieved from the server, stored in my redux store and the displayed with a selector in my react component), but I cannot get the test to succeed.

I would like to test only the redux part, not the actual rendered react component (not sure if that is part of my problem or not)

I use Enzyme for tests, my store is created correctly and can dispatch the action. I can also see that my saga is being called with the console logs:

My test code:

import { Store } from 'redux';

import { RootState } from '../root.reducer';
import { storeFactory } from '../../../test/testUtils';
import { getSecretWord } from './secret-word.actions';

describe('getSecretWord action creator', () => {
  let store: Store<RootState>;
  beforeEach(() => {
    store = storeFactory();
  });
  test('add response word to state', () => {
    const secretWord = 'party';
    store.dispatch(getSecretWord());
    const newState = store.getState();
    console.log('new state: ' + newState.secretWord);
    expect(newState.secretWord).toBe(secretWord);
  });
});

and my saga function:

export function* getSecretWordSaga(action: getSecretWordAction): Generator<ForkEffect | CallEffect | PutEffect, void, unknown>
  {
  try {
    console.log('getSecretWordSaga() saga started');
    console.log('before axios query call:');
    const response:any =  yield call(api.get, '/api/word');
    // const response = {data: { word: 'party'}, status:200}
    
    console.log('axios query returned: ');
    console.log(response);

    yield put(setSecretWord(response.data.word));
    console.log('getSecretWordSaga() saga finsshed');
 
  } catch (err) {
    console.log('error occured:');
    console.log(err);
    console.log('getSecretWordSaga() saga finsshed with errors');
  }
}

export function* getSecretWordSagaStart(): Generator<
  ForkEffect<never>,
  void,
  unknown
> {
  yield takeLatest(SecretWordActionTypes.GET_SECRET_WORD, getSecretWordSaga);
}

The axios api is very basic:

import axios from 'axios';

export const api = axios.create({
  baseURL: 'http://localhost:5000',
  responseType: 'json',
});

I can see in the logs (in "npm test") that I get log for the line "before axios query call:' but no more logs afterwards (neither the successful saga finished, nor the error)

If I comment out the "yield call.." and hardcode the response (like in the commented out line below), my saga runs through the end and my test succeeds.

Why is the yield Call(api.get, '/api/word') not being executed (and I don't get any error message)?

The code is my opinion correct as it is running fine when executed in react. My flask server is obviously also running and I can see in the flask app than no call to the api are being made by the running tests.

I obviously plan to mock that api call but was also running into some problems there, that's why I first wanted to get the real api call working.

Aucun commentaire:

Enregistrer un commentaire