JavaScript - макет консоли в Jest / mock "не назывался"

Я пытаюсь имитировать console.info, который, как я знаю, будет вызываться при запуске импортированной функции. Функция полностью состоит из одного fetch, который, когда он не запущен в производственной среде, сообщает о запросе и ответе с помощью console.info.

На вопрос Шутка. Как смоделировать консоль, когда она используется сторонней библиотекой? самый популярный ответ предлагает перезаписать global.console, поэтому я использую jest.spyOn, чтобы попробовать это:

import * as ourModule from "../src/ourModule";

test("Thing", () => {
    // Tested function requires this. Including it here in case it's causing
    // something quirky that readers of this question may know about
    global.fetch = require("jest-fetch-mock");

    const mockInfo = jest.spyOn(global.console, "info").mockImplementation(
        () => { console.error("mockInfo") }
    );

    ourModule.functionBeingTested("test");
    expect(mockInfo).toHaveBeenCalled();
}

Как и ожидалось, результат содержит экземпляр mockInfo. Однако затем тестирование с toHaveBeenCalled() не удалось.

expect(jest.fn()).toHaveBeenCalled()

Expected mock function to have been called, but it was not called.

  40 |
  41 |     ourModule.functionBeingTested("test");
> 42 |     expect(mockInfo).toHaveBeenCalled();
     |                      ^
  43 | 

  at Object.toHaveBeenCalled (__tests__/basic.test.js:42:22)

console.error __tests__/basic.test.js:38
  mockInfo

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

Вот рассматриваемая функция:

function functionBeingTested(value) {
    const fetchData = {
        something: value
    };

    fetch("https://example.com/api", {
        method: "POST",
        mode:   "cors",
        body:   JSON.stringify(fetchData),
    })
        .then( response => {
            if (response.ok) {
                if (MODE != "production") {
                    console.info(fetchData);
                    console.info(response);
                }
            } else {
                console.error(`${response.status}: ${response.statusText}`);
            }
        })
        .catch( error => {
            console.error(error);
        });
}

Какую функцию библиотеки стороннего производителя вы вызываете?

Brian Adams 19.11.2018 16:17

@ Брайан-живет-на открытом воздухе: Нет, это из другого вопроса.

Scott Martin 19.11.2018 17:15

Можете показать, что делает ourModule.functionBeingTested?

Brian Adams 19.11.2018 17:19

Он получает URL-адрес - я добавил это к вопросу.

Scott Martin 19.11.2018 17:39
Поведение ключевого слова "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) для оценки ваших знаний,...
1
4
1 649
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Проблема

console.info вызывается в обратном вызове Promise, который не выполняется к моменту возврата ourModule.functionBeingTested и запуска expect.

Решение

Перед запуском console.info убедитесь, что обратный вызов Promise, который вызывает expect, запущен.

Самый простой способ сделать это - вернуть Promise из ourModule.functionBeingTested:

function functionBeingTested(value) {
  const fetchData = {
    something: value
  };

  return fetch("https://example.com/api", {  // return the Promise
    method: "POST",
    mode: "cors",
    body: JSON.stringify(fetchData),
  })
    .then(response => {
      if (response.ok) {
        if (MODE != "production") {
          console.info(fetchData);
          console.info(response);
        }
      } else {
        console.error(`${response.status}: ${response.statusText}`);
      }
    })
    .catch(error => {
      console.error(error);
    });
}

... и дождитесь его разрешения, прежде чем утверждать:

test("Thing", async () => {  // use an async test function...
  // Tested function requires this. Including it here in case it's causing
  // something quirky that readers of this question may know about
  global.fetch = require("jest-fetch-mock");

  const mockInfo = jest.spyOn(global.console, "info").mockImplementation(
      () => { console.error("mockInfo") }
  );

  await ourModule.functionBeingTested("test");  // ...and wait for the Promise to resolve
  expect(mockInfo).toHaveBeenCalled();  // SUCCESS
});

Конечно - теперь, когда вы на это указали, это очевидно. Я новичок в асинхронном коде, поэтому мне это не приходило в голову. Огромное спасибо.

Scott Martin 19.11.2018 18:19

@ScottMartin без проблем, рад, что помог

Brian Adams 19.11.2018 18:26

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