Как установить правильное пространство имен в шутке для модуля, прикрепленного к html в браузере, для проверки вызова функции другой функции в этом модуле?

Вопрос сформулирован таким образом, поскольку я могу войти в тестируемый код в среде IDE, и фактический код работает, как и ожидалось, но тест не проходит.

К тестированию HTML с помощью <script src = "../example.js"></script> прикреплен файл javascript, и его содержимое выглядит так:

function myFunc(myId) {
  console.info(myId);
}

function someOtherFunc(arg) {
  if (arg == 0)
    myFunc("#id_0");
  else
    myFunc("#id_1");
}

/*
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* SECTION: exports needed by jest testing framework
* * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
if (typeof exports !== 'undefined') {
  module.exports = {
    myFunc,
    someOtherFunc,
  };
}

А ниже приведено упрощенное содержимое модуля тестирования example.test.js с одним из (многих) неудачных способов протестировать этот вызов:

const fs = require('fs');
const path = require('path');
const html = fs.readFileSync(path.resolve(__dirname, './example.html'), 'utf8');
const jquery = require('../../static/js/jquery-2.2.4.min.js');

window.$ = jquery;
window.jQuery = jquery;

const mockSend = jest.fn();
global.WebSocket = jest.fn();
global.WebSocket.mockImplementation(() => {
  return {
    send: mockSend,
  };
});

const example = require('../example.js');

jest
  .dontMock('fs');

beforeEach(() => {
  document.documentElement.innerHTML = html.toString();
});

afterEach(() => {
  jest.resetModules();
});

describe('someOtherFunc function', function () {
  it('calls myFunc', function () {
    const spyFunc = jest.spyOn(example, "myFunc");
    const result = example.someOtherFunc(0);
    expect(spyFunc).toHaveBeenCalledWith("#id_0")
  });
});

Я вставил эту часть mockSend сюда, так как мне удалось успешно протестировать ее с помощью expect(mockSend).toHaveBeenCalledWith("...");. Этот метод send также находится внутри другой функции, и я тестирую вызывающую функцию в модуле jest.

Однако я не могу найти способ пройти этот тест «вызовы myFunc».

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

Chandan 17.12.2020 16:04

@Chandan, можешь ли ты добавить это в качестве ответа, чтобы я мог его принять?

ipaleka 17.12.2020 16:22
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
493
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Заглушка функции в Javascript требует, чтобы функция была привязана к контексту, любому контексту, который находится в области действия как тестового кода, так и тестируемого кода. В нормальном мире этот контекст предоставляется модулем. Например, в ES5 Node.js:

exports.fn = функция () {}

Чего следует избегать в ES5, так это переопределения module.exports с помощью функции. Слишком много людей делают это, и это неуместно, так как любой модуль, использующий этот код, должен затем предпринять дополнительные шаги, чтобы быть полезным для модульного тестирования:

модуль.экспорт = функция () {}

Как вы можете прочитать из описания, это не работает, потому что myFunc привязан к example.js контексту файла.

Это сработало бы, если бы:

  • Модули импортируются в example.js, например импорт модуля path
  • Обратные вызовы, которые можно передать в функцию при вызове их из теста

Примечание: Для получения более подробной информации вы можете перейти здесь

По описанию решение будет примерно таким:


Решение 1

myFunc.js

function myFunc(myId) {
  console.info(myId);
}

if (typeof exports !== 'undefined') {
  module.exports = myFunc;
}

пример.js

var myFunc = require('./myFunc'); // This needs to be imported using script tag for browser

function someOtherFunc(arg) {
  console.info('inside', myFunc);
  if (arg == 0)
    myFunc("#id_0");
  else
    myFunc("#id_1");
}

if (typeof exports !== 'undefined') {
  module.exports = {
    someOtherFunc
  };
}

пример.test.js

const example = require('../example.js');
const myFunc = require('../myFunc.js');

jest.mock('../myFunc.js');

afterEach(() => {
  jest.resetModules();
});

describe('someOtherFunc function', function () {
  it('calls myFunc', function () {
    const result = example.someOtherFunc(0);
    expect(myFunc).toHaveBeenCalledWith("#id_0")
  });
});

Решение 2

пример.js

function myFunc(myId) {
  console.info(myId);
}

function someOtherFunc(arg) {
  if (arg == 0)
    my_functions.myFunc("#id_0");
  else
    my_functions.myFunc("#id_1");
}

const my_functions = {
  myFunc,
  someOtherFunc,
};

/*
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* SECTION: exports needed by jest testing framework
* * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
if (typeof exports !== 'undefined') {
  module.exports = my_functions;
}

пример.test.js

const example = require('../example');

afterEach(() => {
  jest.resetModules();
});

describe('someOtherFunc function', function () {
  it('calls myFunc', function () {
    const spyFunc = jest.spyOn(example, "myFunc");
    const result = example.someOtherFunc(0);
    expect(spyFunc).toHaveBeenCalledWith("#id_0")
  });
});

Настраивать

пакет.json

{
  "name": "65287977",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/preset-env": "^7.12.11",
    "babel-jest": "^26.6.3",
    "jest": "^26.6.3",
  },
}

Babel.config.js

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          esmodules: true
        }
      }
    ],
  ],
};

Извините, я не могу этого понять. Я могу понять, что это решает вызов jest.spyOn(example, "someOtherFunc"), но как я могу использовать этот «промежуточный программный код» invokeExample для перехвата вызовов jest.spyOn(example, "myFunc")? Кроме того, я не могу понять эту часть «как импорт модуля пути».

ipaleka 17.12.2020 19:36

@ipaleka я обновил свой ответ с примером изменений, необходимых в коде для справки

Chandan 17.12.2020 20:49

Спасибо за ваше время. Я приму этот ответ только благодаря вашим усилиям, но до сих пор не могу найти способ проверить вызов функции из другой функции в том же модуле.

ipaleka 17.12.2020 21:05

@ipaleka я добавил еще одно решение, с помощью которого вы можете проверить вызов функции из другой функции в том же модуле.

Chandan 18.12.2020 03:56

Молодец, большое спасибо! Все дело в запланированном тестировании с самого начала, и это решение доказывает это.

ipaleka 18.12.2020 11:24

Другие вопросы по теме