1

The problem I'm having is that Jest is reporting setResultsSpy is being called 0 times when in fact, I know that it is being called. I know this by putting console.log(results) under the const results = await getFileList(data.path); in my code and was able to see results returned.

My guess right now is that try-catch blocks creates a local scope, which is causing those calls to not be registered. If this is true, my question is "how can I test if those methods have been called"?

// test_myFunction.js

test((`myFunction with valid path should return list of files`), () => {
  const actions = {
    setMsg: () => { },
    setButton: () => {},
    setResults: () => {},
    setAppState: () => {}
  };
  const setMsgSpy = jest.spyOn(actions, 'setMsg');
  const setSubmitButtonStateSpy = jest.spyOn(actions, 'setButton');
  const setResultsSpy = jest.spyOn(actions, 'setResults');
  const setAppStateSpy = jest.spyOn(actions, 'setAppState');
  const returnedFileList = [
    'file1.pdf',
    'file2.pdf',
    'file3.pdf',
  ];
  const requestConfig = {
    component: COMPONENTS.myComponent,
    request: RequestTypes.REQUEST,
    data: {path: 'folder1'},
    actions
  };

  processRequest(requestConfig)

  expect(setMsgSpy).toHaveBeenCalledTimes(1);
  expect(setMsgSpy)
  .toHaveBeenCalledWith('loading');

  expect(setButtonSpy).toHaveBeenCalledTimes(1);

  expect(setResultsSpy).toHaveBeenCalledTimes(1);
  expect(setResultsSpy).toHaveBeenCalledWith(returnedFileList);

  expect(setAppStateSpy).toHaveBeenCalledTimes(1);
  expect(setAppStateSpy).toHaveBeenCalledWith('confirm');
});

_

// myFunction.js
async function processRequest({
  component,
  request,
  data,
  actions,
}){
  if (component === COMPONENTS.myComponent) {
    const path = data.path.trim();
    switch (request) {
      case RequestTypes.REQUEST:
        actions.setMsg('message');
        actions.setButton('disabled');

          try {
            const results = await getFileList(data.path);
            actions.setResults(results);
            actions.setAppState('confirm');
          } catch (e) {
            actions.setError(e);
            actions.setAppState('error');
          }
        }
        break;
      default:
        break;
    }
  }
Alex
  • 1,293
  • 1
  • 13
  • 26

1 Answers1

0

The the problem was Jest was failing out of the test before the results from getFileList() execution has completed since getFileList() is an async function.

The solution is for the test to handle the execution asynchronously as per the documentation. There are 4 ways to solve this problem:

  1. Use callbacks
  2. Use .then() and .catch() on the returned promise (see docs on .then() here and .catch() here)
  3. Use .resolves() or .rejects() Jest methods on expect() to let Jest resolve the promise.
  4. Use Async-Await syntax by declaring the test anonymous function as async and using await on processRequest() .

I went with option 4 as I enjoy using async-await syntax. Here's the solution:

// test_myFunction.js

test((`myFunction with valid path should return list of files`), async () => {
  //(all of the variables established from above)    

  await processRequest(requestConfig)

  expect(setMsgSpy).toHaveBeenCalledTimes(1);
  expect(setMsgSpy)
  .toHaveBeenCalledWith('loading');

  expect(setButtonSpy).toHaveBeenCalledTimes(1);

  expect(setResultsSpy).toHaveBeenCalledTimes(1);
  expect(setResultsSpy).toHaveBeenCalledWith(returnedFileList);

  expect(setAppStateSpy).toHaveBeenCalledTimes(1);
  expect(setAppStateSpy).toHaveBeenCalledWith('confirm');
});

Notice async being used on the first line and await when calling processRequest(requestConfig).

Alex
  • 1,293
  • 1
  • 13
  • 26