تصلني هذه الرسالة في كل مرة أستخدم فيها أي مكتبات تعتمد على الوعود.
لم تخرج Jest ثانية واحدة بعد اكتمال التشغيل التجريبي.
يعني هذا عادةً وجود عمليات غير متزامنة لم يتم إيقافها في اختباراتك. ضع في اعتبارك تشغيل Jest مع --detectOpenHandles
لاستكشاف هذه المشكلة وإصلاحها.
لدي وظيفة تحتاج إلى تقديم طلب لواجهة برمجة تطبيقات خارجية ، وبنفس الطريقة فقط احفظها في قاعدة البيانات دون انتظار الرد.
لا أريد الانتظار حتى تتم عملية الحفظ ، لكنني مضطر إلى تغيير سلوك تطبيقي لاختباره من خلال الدعابة. ، أو أحتاج إلى إغلاق الاتصال ، وإيقاف الخادم حتى يعمل الكود الخاص بي .
دعابة مقتطعة للتوقف والعودة إلى وحدة التحكم الخاصة بي.
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 ، ولكن رد الاتصال هذا ، من أين يجب أن أصل؟
إنه عميق جدًا داخل الخادم.
انتقلت إلى آفا ، إنها تعمل خارج الصندوق 👍
حسنًا ، أخي الدنماركي :)
تكمن المشكلة في أنني أستخدم النمس لحفظ شيء غير متزامن عندما أسمي هذا api ، ولا يمكنني الوصول إلى هذا الرمز لمعرفة متى ينتهي حفظ المستند داخل mongo.
await server.inject
في الواقع ، ينتظر الكود أعلاه الرد فقط ، وهو يعمل ، ولكن مازحًا يشكو من حفظ النمس ، فهو لا يزال قيد التقدم في الحفظ خلف الكواليس.
حاولت فصل النمس وإغلاق كل اتصال ، لكنه لم ينجح.
لقد تلقيت نفس الخطأ في أحد اختبارات التكامل الخاصة بي. في ذلك ، كنت أستخدم نموذج Sequelize لإعداد قاعدة البيانات إلى حالة معروفة في 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();
});
تضمين التغريدة
تضمين التغريدة
أضفت مثالا.
لقد تلقيت نفس الخطأ في أحد اختبارات التكامل الخاصة بي. في ذلك ، كنت أستخدم نموذج Sequelize لإعداد قاعدة البيانات إلى حالة معروفة في
beforeAll
. كان الإصلاح هو استدعاءclose
على مثيل Sequelize المتصل بالنموذج في رد الاتصالafterAll
. آمل أن يساعد هذا شخص آخر.
ما هو إصدار Sequelize الذي تستخدمه؟ أحصل على sequelizeInstance.close()
ليست وظيفة.
لقد تلقيت نفس الخطأ في أحد اختبارات التكامل الخاصة بي. في ذلك ، كنت أستخدم نموذج Sequelize لإعداد قاعدة البيانات إلى حالة معروفة في
beforeAll
. كان الإصلاح هو استدعاءclose
على مثيل Sequelize المتصل بالنموذج في رد الاتصالafterAll
. آمل أن يساعد هذا شخص آخر.
هل يمكنك إظهار الكود الخاص بك؟
مرحبًا ، لقد تلقيت نفس الخطأ ، مع @ dhurlburtusa tip ، كان الرمز الخاص بي هو 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
هو الوظيفة التي تتصل بالفعل بمثيل قاعدة البيانات.
لقد تلقيت نفس الخطأ في أحد اختبارات التكامل الخاصة بي. في ذلك ، أستخدم 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
أقوم بالاتصال بـ db وأعيد وظيفة ترجع الوعد. وبالمثل في teardownTests
أقوم بإغلاق اتصال db وأعد وظيفة ترجع الوعد.
كنت أواجه هذه المشكلة مع 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 لم يخرج ثانية واحدة ..." بالنسبة لنا كان نتيجة عدم إغلاق محول MongoDB الخاص بـ Parse بشكل صحيح.
لذا للتغلب على هذه المشكلة ، قمت بتجريد تهيئة الخادم تمامًا من مجموعة اختبار jest وأنشأت برنامجًا نصيًا خاصًا 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
وهو الأمر العادي الذي سنقوم بتشغيله لبدء تشغيل خادمنا باستخدام Express و Parse.start
في الخلفية ونبدأ عملية منفصلة تقوم بتشغيل برنامج shell script ( 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
بطباعة أي شيء إلى وحدة التحكم.
تواجه نفس المشكلة حاول إغلاق اتصال تكملة ، لا حظ هناك.
على الرغم من أن المشكلة قد لا تتعلق بالمزح ولكن مشكلتها الرئيسية هي أنها لا تعرض العمليات النشطة. --detectOpenHandles
لا يطبع أي شيء: confused:
في الجزء العلوي ، إذا استخدمنا --forceExit ، فستظهر رسالة لاستخدام --detectOpenHandles
السخرية: -1:
لقد كنت أواجه هذه المشكلة أيضًا
انتهى بي الأمر باستخدام https://www.npmjs.com/package/why-is-node-running تسجيل الدخول قبل الكل
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
.
يبدو الإعداد و teardown كما يلي:
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
لا تزال تعمل أثناء تشغيل المزاح.
ومع ذلك ، بمجرد إلغاء / إنهاء التشغيل التجريبي ، يتم إنهاء العمليات أيضًا.
سأقوم بمزيد من الاستقصاء عن طريق أخذ عينات من عمليات العقدة وأرى بالضبط ما يولدها. سوف أقوم بتحديث النتائج التي توصلت إليها هنا.
تحرير: المشكلة ذات الصلة رقم 1456 - يبدو أنها مشكلة أساسية في NodeJS. tl ؛ dr - أضف علامة --forceExit
إلى نص الاختبار الخاص بك في package.json
أهلا! يبدو أنك لم تقم بعد بقطع الاتصال بقاعدة البيانات. لقد جربت وظيفة mongoose.disconnect()
في afterAll()
وهي لا تظهر رسالة كهذه بعد الآن.
BigsonLvrocha أشكرك على هذه الفكرة لإعادة: 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 ().
في الاختبار ، قمت بحل مشكلة إغلاق اتصال النمس بشكل صحيح باستخدام الاتصال. قطع الاتصال ().
لكن الاختبارات الأخرى تقدم الرسالة حتى الآن. لقد لاحظت أن جميع اختباراتي التي تستخدم الحزمة الفائقة تحافظ على الرسالة.
الطريقة هي تحليل كل حالة على حدة.
ماذا لو لم أستدعي قاعدة بيانات؟ ماذا لو اتصلت بمورد خارجي ليس لدي سيطرة عليه؟ كيف "أغلق"؟
YounesTea قد يكون لديك مكالمة غير
حاول الاتصال بـ done()
بعد أن تكون قد انتهيت 😉
it("Should test something", async (done) => {
// Sends request...
const req = await request(app).get("/someEndpoint");
expect(req).toBeTruthy();
done();
});
YounesTea قد يكون لديك مكالمة غير
حاول الاتصال بـdone()
بعد أن تكون قد انتهيتit("Should test something", async (done) => { // Sends request... const req = await request(app).get("/someEndpoint"); expect(req).toBeTruthy(); done(); });
لدي غير متزامن / ينتظر وأنا أستخدم بالفعل رد الاتصال المنجز () في الاختبارات بما في ذلك beforeAll و afterAll.
استمرت المشكلة ...
beforeAll (غير متزامن () => {
في انتظار firebase.firestore (). enableNetwork () ؛
}) ؛afterAll (غير متزامن () => {
في انتظار firebase.firestore (). disableNetwork () ؛
}) ؛
هذا لا يعمل. ومع ذلك ، هذا واحد يعمل:
afterAll(async () => {
await app.delete()
})
في mongo لقد حللت هذا:
`afterAll(async(done) => {
// Closing the DB connection allows Jest to exit successfully.
await mongoose.connection.close()
done()
})`
التعليق الأكثر فائدة
لقد تلقيت نفس الخطأ في أحد اختبارات التكامل الخاصة بي. في ذلك ، كنت أستخدم نموذج Sequelize لإعداد قاعدة البيانات إلى حالة معروفة في
beforeAll
أوbeforeEach
. كان الإصلاح هو استدعاءclose
على مثيل Sequelize المتصل بالنموذج في رد الاتصالafterAll
. آمل أن يساعد هذا شخص آخر.تم تحريره:
ووفقًا للطلب الشائع ، فإليك ما فعلته بشكل فعال:
تضمين التغريدة
تضمين التغريدة
أضفت مثالا.