общие JS требуется экспортированная функция по умолчанию возвращает функцию по умолчанию - PullRequest
0 голосов
/ 06 февраля 2020

Я наткнулся на что-то в JavaScript, что я нашел сбивающим с толку, и я надеюсь найти объяснение для.

Я пишу Jest-тест, для которого требуется дразнить пользовательский модуль, который я ' Я написал, от чего зависит вспомогательная функция, которую я тестирую. Кроме того, мне нужно переопределить метод из пользовательского модуля, чтобы изменить его обычный вывод, чтобы вместо этого выдать исключение, чтобы проверить несчастный путь.

Вот как выглядит мой фиктивный модуль:

// ../helperFunctions/__mocks__/CreateRequestObject.js

// This is the mock function for getFileList()
export default function () {
 return {
    post: () => ({
      data: [
       "folder1/file1.doc",
       "folder1/folder2/file2.doc",
       "folder1/folder3/file3.doc"
      ],
    }),
  };
}
// ../helperFunctions/CreateRequestObject.js

/* This function returns an axios request object with pre-configured base url */

import axios from 'axios';

export default function (config = {
  baseURL: 'https://www.example.com',
  timeout: 10000,
  responseType: 'json',
}) {
  return axios.create({
    baseURL: config.baseURL,
    timeout: config.timeout,
    responseType: config.responseType,
  });
}
// ../helperFunctions/RequestActions.js
import createRequestObject from './CreateRequestObject';
import RequestException from '../exceptions/RequestExceptions';

async function getFileList(path) {
  /*
    Returns:
    * [] if there are no files or folders found in the path
    * An array of file names as strings if one or more files are found

    Throws:
    * RequestException when request fails
  */

  try {
    const api = createRequestObject();
    const response = await api.post('/endpoint', { path });
    const dataSet = response.data;
    return dataSet;
  } catch (e) {
    throw new RequestException(e);
  }
}

export default getFileList;
// ../helperFunctions/helperFunctions.test.js
import createRequestObject from '../helperFunctions/CreateRequestObject';
import getFileList from '../helperFunctions/RequestActions';
import RequestException from '../exceptions/RequestExceptions';

test(`getFileList() API call failure should throw RequestException error`,
  async () => {
    // Arrange
    const path = 'folder1/folder2/folder3';

    const createRequestObject = require('../helperFunctions/CreateRequestObject');
    createRequestObject.default.post.mockImplementation() => ({
        post: () => {
          throw new RequestExeception({
            message: 'No Network',
            config: {
              baseURL: 'https://www.example.com',
              url: '/endpoint',
          })
        }
      }));

    // Act
    const data = await getFileList(path);

    // Assert
    expect(data).toThrow();

  });

Из документации Джестса предлагается сначала вызвать jest.mock('path/to/module/tobe/mocked');, а затем запросить исходный файл const myModule = require('path/to/module/tobe/mocked');. После этого вызовите myModule.methodName.mockImplementation(() => {...}); в моем тесте, чтобы изменить реализацию.

Однако, когда я пытаюсь вызвать метод после require, я получаю сообщение о том, что метод не существует. Выполнение console.log() показывает [default: Function_].

Из любопытства я позвонил console.log(myModule.default()) и вижу { post: [Function post] }.

Переход к файлу макета модуля с использованием VSCode и наведение мыши поверх ключевого слова default я вижу следующее наложение:

function default(): {
   post: () => ({ data: string[] });
}

Мой вопрос: почему по умолчанию возвращается как функция, когда мне требуется файл, использующий ключевые слова export default? Как работает функция экспорта по умолчанию?

Кроме того, вызов mockImplementation не работает, и я не понимаю, почему.

1 Ответ

0 голосов
/ 07 февраля 2020

Проблема

Я не уверен, что это способ решить эту проблему. Я приветствую других, которые более склонны к настройке тестов с помощью Jest Framework.

Изначально я думал, что должен структурировать тест:

  1. Создайте фиктивную версию моего пользовательского модуля createRequestObject в /helperFunctions/__mocks__/CreateRequestObject.js

  2. В HelperFunctions.test. js, вызовите jest.mock('../helperFunctions/CreateRequestObject')

  3. добавить import createRequestObject from '../helperFunctions/CreateRequestObject' вверху, затем в моем указанном c тесте позвонить createRequestObject.mockImplementation(() => { throw new RequestException(...)}

Когда я это сделал, я столкнулся с сообщением об ошибке "createRequestObject" не является функцией.

Это потому, что когда функция была импортирована, функция выполнила и вернула объект.

Следующая проблема состояла в том, что объект является фиксированным объектом, содержащим метод post который возвращает объект с некоторыми данными внутри. Ничто из этого не может быть изменено. Думайте об этом как о постоянном c неизменяемом изображении.

Мне нужна возможность изменять реализацию моего модуля на лету между тестами, чтобы моя вспомогательная функция getFileList() вызывала createRequestObject() за кулисами: а) вернуть набор данных, имитирующих успешный вызов API, или б) выдать ошибку при сбое вызова API.

Решение

Внутри /helperFunctions/__mocks__/CreateRequestObject.js, теперь у меня есть следующий код:

export default jest.fn();

jest.fn() вернет объект с доступом ко всем методам насмешек, которые мне нужны, чтобы изменить реализацию на лету!

В моем HelperFunctions.test.js теперь я могу импортировать createRequestObject, как я это делал выше, но теперь несколько раз вызываю createRequestObject.mockImplementationOnce(() => {...}) для настройки моих тестов, что и является моим намерением!

Надеюсь, эта информация поможет другие, которые также сталкиваются с аналогичными проблемами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...