Я получаю это сообщение каждый раз, когда использую какие-либо библиотеки, зависящие от обещаний.
Jest не выходил через одну секунду после завершения тестового запуска.
Обычно это означает, что есть асинхронные операции, которые не были остановлены в ваших тестах. Для устранения этой проблемы рассмотрите возможность запуска Jest с --detectOpenHandles
.
У меня есть функция, которая должна сделать запрос к внешнему API, и в том же методе просто сохранить в базе данных, не дожидаясь ответа.
Я не хочу дожидаться завершения процесса сохранения, но я вынужден изменить поведение моего приложения, чтобы протестировать его с помощью шутки. Или мне нужно закрыть соединение, остановить сервер, чтобы мой код работал .
Исключенная шутка остановиться и вернуться к консоли.
test("it should create new order", async () => {
const response = await server.inject({
method: "POST",
url: "/api/orders",
payload: JSON.stringify({
customer: {
email: "[email protected]",
phone: "20 51 75 95",
city: "Aarhus",
zip: "8000",
first_name: "jamal",
last_name: "soueidan"
},
properties: [
{
name: "custom engraving",
value: "Happy Birthday Mom!"
}
]
})
});
expect(response.statusCode).toBe(200);
});
Мне пришлось внести эти изменения, чтобы шутка работала с моим сервером api и mongodb.
https://github.com/jamalsoueidan/giv-et-tilbud/commit/d8f326b6294f88d1f12136042d4adfdc83328201
npx envinfo --preset jest
System:
OS: Windows 10
CPU: x64 Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
Binaries:
npm: 6.4.1 - C:\Program Files\nodejs\npm.CMD
Попробуйте поместить "готово" в обратный вызов из тестовой функции следующим образом:
const whateverYouExpect = 123;
test('some description of test', async (done) => {
await someAsyncTask();
await secondAsyncTask();
evenCallbacksCanWork((result) => {
expect(result).toBe(whateverYouExpect);
done();
});
})
Кроме того, если соединение остается открытым, это также остановит выполнение теста, поэтому также рекомендуется закрыть любое открытое соединение.
Спасибо ExoMemphiz, но этот обратный вызов, откуда я должен связаться с ним?
Это слишком глубоко внутри сервера.
Перешел на Аву, из коробки работает 👍
Ну что ж, брат мой датчанин :)
Проблема в том, что я использую mongoose, чтобы сохранить что-то асинхронно, когда я вызываю этот api, и я не могу добраться до этого кода, чтобы выяснить, когда он завершил сохранение документа внутри mongo.
await server.inject
Приведенный выше код на самом деле ждет только ответа, и он работает, но шутка жалуется на сохранение мангуста, он все еще находится в процессе сохранения за сценой.
Я пытался отключить мангуста и закрыть каждое соединение, но это не сработало.
Я получал ту же ошибку в одном из моих интеграционных тестов. В нем я использовал Sequelize Model для установки базы данных в известное состояние в beforeAll
или beforeEach
. Исправление заключалось в вызове close
экземпляра Sequelize, подключенного к модели, в обратном вызове afterAll
. Надеюсь, это поможет кому-то другому.
ИЗМЕНИТЬ:
И по многочисленным просьбам вот что я фактически сделал:
# dbConnection.js
export default new Sequelize({...}); // The Sequelize instance.
# some.spec.js
import dbConnection from './dbConnection';
const { SomeModel } = dbConnection.models;
describe('...', () => {
beforeEach(async () => {
await SomeModel.create({...});
});
...
});
afterAll(async done => {
// Closing the DB connection allows Jest to exit successfully.
dbConnection.close();
done();
});
@ Shrikant9
@AnitaMartinez
Я добавил пример.
Я получал ту же ошибку в одном из моих интеграционных тестов. В нем я использовал Sequelize Model для установки базы данных в известное состояние в
beforeAll
. Исправление заключалось в вызовеclose
в экземпляре Sequelize, подключенном к модели, в обратном вызовеafterAll
. Надеюсь, это поможет кому-то другому.
Какую версию Sequelize вы используете? Я получаю sequelizeInstance.close()
не функция.
Я получал ту же ошибку в одном из моих интеграционных тестов. В нем я использовал Sequelize Model для установки базы данных в известное состояние в
beforeAll
. Исправление заключалось в вызовеclose
в экземпляре Sequelize, подключенном к модели, в обратном вызовеafterAll
. Надеюсь, это поможет кому-то другому.
Вы можете показать свой код?
Привет, я получал ту же ошибку, с подсказкой @dhurlburtusa , мой код был @AnitaMartinez , я новичок в TypeScript, поэтому я почти уверен, что это можно сделать лучше:
let conn: Connection;
const createGlobalDatabaseConnection = (fn: Function) => dbConnection().then((conn: Connection) => fn(conn));
createGlobalDatabaseConnection((connection: Connection) => {
conn = connection;
});
const closeGlobalDatabaseConnection = async () => {
await conn.close();
}
afterAll(async () => {
await closeGlobalDatabaseConnection();
});
dbConnection
Promise - это функция, которая фактически подключается к экземпляру базы данных.
Я получал ту же ошибку в одном из моих интеграционных тестов. В нем я использую mongo
. Исправление заключалось в вызове закрытия mongoose.connection
. Надеюсь, это поможет кому-то другому.
const mongoose = require('mongoose')
describe(' ...... ', ()=>{
afterAll( async () =>{
await mongoose.connection.close()
})
})
Была эта проблема с тестами, которые использовали firebase. Это исправлено:
beforeAll(async () => {
await firebase.firestore().enableNetwork();
});
afterAll(async () => {
await firebase.firestore().disableNetwork();
});
Если у вас несколько тестовых файлов, я использую глобальную настройку и разборку. Например, в jest.config.js
я определил:
module.exports = {
globalSetup: './setupTests.js',
globalTeardown: './teardownTests.js',
};
В setupTests
я подключаюсь к базе данных и возвращаю функцию, которая возвращает обещание. Точно так же в teardownTests
я закрываю соединение с базой данных и возвращаю функцию, которая возвращает обещание.
У меня была эта проблема с Knex и с использованием глобальных файлов настройки и удаления на Jest.
Мое решение было:
// setup.js
const knexConfiguration = require('../config/knex')[process.env.NODE_ENV];
const knex = require('knex');
const setup = async () => {
const client = knex(knexConfiguration)
await client.migrate.latest();
await client.destroy();
};
module.exports = setup;
// teardown.js
const knexConfiguration = require('../config/knex')[process.env.NODE_ENV];
const knex = require('knex');
const teardown = async () => {
const client = knex(knexConfiguration)
await client.migrate.rollback();
await client.destroy();
};
module.exports = teardown;
Надеюсь, это поможет любому, кто сталкивается с такой проблемой.
Всем привет,
Пожалуйста, поправьте меня, если я ошибаюсь, но это похоже на проблему, которая не на стороне Jest.
Если вы хотите, чтобы тесты завершались даже при наличии внешних ресурсов, я думаю, вам следует использовать --forceExit
. Флаг forceExit
специально разработан для этого случая и, следовательно, указывает на то, что невыполнение тестов, когда его нет, действительно является ожидаемым поведением, а не ошибкой.
Принудительно закрыть Jest после завершения всех тестов. Это полезно, когда ресурсы, настроенные тестовым кодом, не могут быть должным образом очищены. Примечание: это аварийный выход. Если Jest не завершается в конце тестового прогона, это означает, что внешние ресурсы все еще удерживаются или таймеры все еще ожидают в вашем коде. Рекомендуется отключать внешние ресурсы после каждого теста, чтобы убедиться, что Jest может корректно завершить работу.
Как упомянул автор, для отладки этого можно использовать --detectOpenHandles
(и это также упоминается в документации, кстати).
Учитывая приведенные выше аргументы, возможно, этот вопрос можно было бы закрыть?
@lucasfcosta Каждый раз, когда я пытался использовать --detectOpenHandles
в своем тестовом коде в нескольких разных приложениях на протяжении многих лет, он никогда не давал мне никаких полезных результатов. Он просто сидит и ждет, пока все завершится, но не выводит предупреждение, предлагающее в первую очередь использовать аргумент. Есть ли какой-нибудь трюк для получения полезного вывода из этого аргумента, о котором я не знаю?
Есть ли другой способ отладки? --detectOpenHandles
не показывает никаких результатов. Спасибо
То же самое. Я не получаю вывода из --detectOpenHandles
.
$ yarn test:types && jest --config ../../jest.config.js --detectOpenHandles
$ tsc --noEmit
PASS src/App.test.tsx (9.447s)
√ renders without crashing (240ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.201s, estimated 14s
Ran all test suites.
(node:9784) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1126:14)
(node:9784) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a prom
ise which was not handled with .catch(). (rejection id: 2)
(node:9784) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-z
ero exit code.
Мой jest.config.js :
module.exports = {
bail: true,
collectCoverage: false,
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/index.tsx', '!src/main.ts', '!**/node_modules/**'],
coverageDirectory: '<rootDir>/coverage',
coverageThreshold: {
global: {
branches: 100,
functions: 100,
lines: 100,
statements: 100,
},
},
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx'],
rootDir: process.cwd(),
testMatch: ['<rootDir>/src/**/*.test.{ts,tsx}'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
verbose: true,
};
Мой тестовый пример:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
Для тех, кто сталкивался с этим с помощью sequelize
, мне пришлось сделать следующее:
afterAll(async done => {
await models.sequelize.close();
done();
});
Это устранило проблему.
Я тестирую Jest с помощью мангуста и супертеста, добавил testEnvironment: 'node'
исправил эту проблему для меня.
Еще одна возможная причина, с которой я столкнулся - не закрытое соединение Redis.
afterAll(async done => {
globalRedisClient.unref();
done();
});
Мое решение не сработает для всех, но если вы рыскали по сети, пока я пытался выяснить, как закрыть этот проклятый дескриптор, который остался открытым, это может помочь. В моей экосистеме мы запускаем Parse Server в качестве промежуточного программного обеспечения с Express-сервером, но это может относиться к любому, кому нужно запустить отдельный сервер с тестами, но не может закрыть какой-то сокет или порт в конце. Я _ верю_, что проблема, вызывающая ужасную ошибку «Jest не завершилась одна секунда ...» для нас, была результатом неправильного закрытия адаптера Parse MongoDB.
Поэтому, чтобы обойти эту проблему, я полностью выделил инициализацию сервера из набора шутливых тестов и создал специальный сценарий npm для его запуска в совершенно отдельном процессе.
Скрипт NPM (package.json):
"scripts": {
"test": "npm start & ./listen_on_port_5000.sh && jest test && kill $(lsof -t -i tcp:5000)",
}
listen_on_port_5000.sh
while ! nc -z localhost 5000
do
sleep 0.5
done
Так, как это работает?
npm start
run - это обычная команда, которую мы выполняем для запуска нашего сервера с помощью Express и Parse.start
в фоновом режиме и запускаем отдельный процесс, запускающий сценарий оболочки ( listen_on_port_5000.sh
), чтобы дождаться загрузки сервера. .jest
(все время, пока сервер Express запущен и работает).kill
чтобы закрыть сервер, работающий на порту 5000.У меня были тесты, которые проверяли автоматически сгенерированные соединения http-сервера и socket.io.
Тесты прошли нормально на моей машине с Windows, но не завершились из-за того, что не вышли на моем сервере Jenkins.
Я правильно закрывал и сервер socket.io, и http-сервер в конце теста, но я не закрывал клиентов. После того, как я добавил очистку для клиентов, тесты успешно завершились самостоятельно как на моей машине разработчика, так и на сервере CI.
Тесты работали бы без закрытия клиентов, если бы я использовал --forceExit
, но, в конце концов, настоящая проблема заключалась в неправильной очистке.
Я также обнаружил, что --detectOpenHandles
ничего не выводит.
Я столкнулся с той же проблемой с хуками globalSetup
и globalTeardown
, но я не могу найти никаких процессов, оставшихся без присмотра. Я добавил done()
в конец всех тестов и останавливаю свой сервер во время разборки.
jest --runInBand --detectOpenHandles
ничего не выводит на консоль.
Я столкнулся с той же проблемой с хуками
globalSetup
иglobalTeardown
, но я не могу найти никаких процессов, оставшихся без присмотра. Я добавилdone()
в конец всех тестов и останавливаю свой сервер во время разборки.
jest --runInBand --detectOpenHandles
ничего не выводит на консоль.
Столкнувшись с той же проблемой, попытался закрыть соединение sequelize, не повезло.
Хотя проблема может быть не в шутке, но ее основная проблема в том, что он не показывает, какие процессы активны. --detectOpenHandles
ничего не печатает: confused:
Вверху, если мы используем --forceExit, отображается сообщение об использовании --detectOpenHandles
Ирония: -1:
У меня тоже была эта проблема
В итоге я использовал https://www.npmjs.com/package/why-is-node-running, входя в систему beforeAll
import log from 'why-is-node-running';
afterAll(async () => {
//normal cleanup things
await new Promise(resolve => {
setTimeout(() => {
log()
resolve()
}, 4000)
})
}
Оказывается, поскольку я использовал jest.resetModules, мне пришлось повторно импортировать модуль, который использовал соединение pg, и закрыть его там тоже.
У меня тоже такая проблема. Чтобы дать некоторый контекст, я использую SuperTest для тестирования e2e с MongoMemoryServer
.
Моя установка и разборка выглядят так:
let mongoServer;
beforeAll(async (done) => {
mongoServer = new MongoMemoryServer({ instance: { port: 26016 } });
const uri = await mongoServer.getUri();
process.env.MONGODB_URI = uri;
done();
});
afterAll(async (done) => {
await mongoServer.stop();
done();
});
Ничего необычного, что могло бы свидетельствовать о том, что я неправильно слежу за документацией.
Я начал устранение неполадок с просмотра Activity Monitor
в MacOS. Кажется, что есть два процесса node
, которые все еще работают, пока выполняется jest.
Однако, как только я отменяю / выхожу из тестового прогона, процессы также завершаются.
Я собираюсь исследовать дальше, отобрав процессы узлов и посмотрим, что именно их порождает. Я обновлю здесь свои выводы.
РЕДАКТИРОВАТЬ: Связанная проблема № 1456 - похоже, что это основная проблема NodeJS. tl; dr - добавьте флаг --forceExit
в свой тестовый скрипт в package.json
Привет! Похоже, вы еще не отключились от базы данных. Я пробовал mongoose.disconnect()
в функции afterAll()
и он больше не показывает такое сообщение.
@BigsonLvrocha спасибо за идею re: why-is-node-running
! В моем случае этот инструмент показал мне, что redux-state-sync
инициализируется в тестах, в которых есть бесконечный цикл для прослушивания обновлений Redux. --detectOpenHandles
мне тоже ничего не вывел.
Я тестирую свое приложение React Native и получаю это. Я получаю данные из BE и использую moxios
. Затем я отправляю действие по обновлению магазина. Я использую "jest": "^26.4.2",
test('dispatch paperPlanes/set action correctly updates the store', async done => {
// Mock the response to /paperPlane/list
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: expectedResponse,
});
});
// Execute the api call to /paperPlane/list
const res = await axios.get('/paperplane/list');
const action = actionCreators.paperPlanes.set(res.data.paper_planes);
store.dispatch(action);
const newState = store.getState();
expect(newState.paperPlanes.paperPlanes).toEqual(
expectedResponse.paper_planes,
);
done();
});
У меня есть эта ошибка в нескольких тестах шутки. Я закрываю экспресс-сервер правильно с помощью server.close ().
На тесте я решил проблему с закрытием соединения мангуста с помощью connection.disconnect ().
Но другие тесты пока не показывают этого сообщения. Я заметил, что все мои тесты, в которых используется супертестовый пакет, сохраняют сообщение.
Способ состоит в том, чтобы анализировать от случая к случаю.
Что делать, если я не вызываю базу данных? Что делать, если я вызываю внешний ресурс, над которым не имею контроля? Как мне "закрыть"?
@YounesTea, у вас может быть вызов async / await в вашем коде.
Попробуйте позвонить в done()
после того, как все будет хорошо 😉
it("Should test something", async (done) => {
// Sends request...
const req = await request(app).get("/someEndpoint");
expect(req).toBeTruthy();
done();
});
@YounesTea, у вас может быть вызов async / await в вашем коде.
Попробуйте позвонитьdone()
после того, как вы, хорошо, сделалиit("Should test something", async (done) => { // Sends request... const req = await request(app).get("/someEndpoint"); expect(req).toBeTruthy(); done(); });
У меня есть async / awaits, и я уже использую обратный вызов done () в тестах, включая beforeAll и afterAll.
Проблема не устранена ...
beforeAll (async () => {
ждать firebase.firestore (). enableNetwork ();
});afterAll (async () => {
ждать firebase.firestore (). disableNetwork ();
});
Это не работает. Однако это работает:
afterAll(async () => {
await app.delete()
})
в монго я решил это:
`afterAll(async(done) => {
// Closing the DB connection allows Jest to exit successfully.
await mongoose.connection.close()
done()
})`
Самый полезный комментарий
Я получал ту же ошибку в одном из моих интеграционных тестов. В нем я использовал Sequelize Model для установки базы данных в известное состояние в
beforeAll
илиbeforeEach
. Исправление заключалось в вызовеclose
экземпляра Sequelize, подключенного к модели, в обратном вызовеafterAll
. Надеюсь, это поможет кому-то другому.ИЗМЕНИТЬ:
И по многочисленным просьбам вот что я фактически сделал:
@ Shrikant9
@AnitaMartinez
Я добавил пример.