Я пытаюсь имитировать 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);
});
}
@ Брайан-живет-на открытом воздухе: Нет, это из другого вопроса.
Можете показать, что делает ourModule.functionBeingTested?
Он получает URL-адрес - я добавил это к вопросу.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


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
});
Конечно - теперь, когда вы на это указали, это очевидно. Я новичок в асинхронном коде, поэтому мне это не приходило в голову. Огромное спасибо.
@ScottMartin без проблем, рад, что помог
Какую функцию библиотеки стороннего производителя вы вызываете?