Jest: غير متزامن / انتظار toThrow لا يعمل

تم إنشاؤها على ١٥ سبتمبر ٢٠١٦  ·  21تعليقات  ·  مصدر: facebook/jest

الاختبار التالي

async function check() {
  throw new Error('Test');
}

expect(async () => 
  await check()
).toThrow();

ستفشل ولن يتم اكتشاف الخطأ بشكل صحيح (أنا أستخدم أحدث إصدار من المزاح)

التعليق الأكثر فائدة

بدلا من

expect(async () => await check()).toThrow()
// Jest error: "Expected the function to throw an error. But it didn't throw anything."

هذا يعمل:

expect(check()).rejects.toEqual(new Error('Test'))

نعم ، بناء الجملة محرج ...

ال 21 كومينتر

نعم ، هذا غير مدعوم حاليًا. راجع https://github.com/facebook/jest/issues/1377

بدلا من

expect(async () => await check()).toThrow()
// Jest error: "Expected the function to throw an error. But it didn't throw anything."

هذا يعمل:

expect(check()).rejects.toEqual(new Error('Test'))

نعم ، بناء الجملة محرج ...

يمكنك أيضًا كتابة:

let error;
try {
  await check();
} catch (e) {
  error = e;
}
expect(error).toEqual(new Error('Test'));

ما يلي يعمل معي أيضًا:

async function check() {
  throw new Error('Test');
}

expect(check()).rejects.toEqual(new Error('Test'))

انظر: https://facebook.github.io/jest/docs/en/tutorial-async.html#rejects

إضافة إلى قائمة الحلول.
إذا كنت ترغب في التعرف على نوع خطأ معين ، ولا تهتم بالرسالة:

async function check() {
  throw new SomeSpecificError('Whatever');
}

await check()
  .then(() => {
    throw new Error('Should go to .catch, not enter .then');
  })
  .catch((err) => {
    expect(err).toBeInstanceOf(SomeSpecificError);
  });
await expect(check).rejects.toThrow(SomeSpecificError);

يجب أن تعمل كذلك

await expect(check).rejects.toThrow(/DUPLICATES_DETECTED/);

هو ما أفعله.

async function check() {
  throw new Error("Test");
}
await expect(check).rejects.toThrow(Error);
expect(received).rejects.toThrow()

received value must be a Promise.
Received:
 function: [Function check]

عليك أن تستدعيها لتعطيها الوعد الفعلي

async function check() {
  throw new Error("Test");
}
await expect(check()).rejects.toThrow(Error);

يجب أن تعمل كذلك

it(`some test`, async () => {
  async function check() {
    try {
      return Promise.reject(await asyncMethod());
    } catch (error) {
      throw new Error("test");
    }
  }
  await expect(check()).rejects.toThrow(Error);
});

يمكن أن تعمل

إصدار

  • دعابة: 23.4.2
  • ts-jest: 23.1.2

أعلم أنه بحاجة إلى وعد ، لكن الحالة التي تعرضها ليست كذلك :)

أهلا ! ربما أكون أفعل شيئًا خاطئًا ، لكن لا يزال لدي مشكلة في الأخطاء المخصصة في المكالمات غير المتزامنة. ضع في اعتبارك ما يلي:

class CustomErrorType {}
// ...
test('check throws custom error', async () => {            
    async function check() {
        throw new CustomErrorType();
    }
    await expect(check()).rejects.toThrow(CustomErrorType);
});

ثم يفشل الاختبار بالمخرجات التالية:

من المتوقع أن تؤدي الوظيفة إلى ظهور خطأ من النوع:
"CustomErrorType"
لكنها لم ترمي أي شيء.

لذا فشل الاختبار - في حين أنه يعمل بشكل مثالي عندما يكون الفصل الذي تم إلقاؤه هو Error . عندما أحاول تمديد Error مع
`` جافا سكريبت
تمدد فئة CustomErrorType خطأ {}
""

ثم الخطأ

من المتوقع أن تؤدي الوظيفة إلى ظهور خطأ من النوع:
"CustomErrorType"
بدلاً من ذلك ، ألقى:
خطأ

أي دليل على شيء ما هو الخطأ في تلك العينة؟ أنا أستخدم المزحة 23.4.2.

Marchelune عندما تكتب class CustomErrorType extends Error {} فأنت لا تعرف بالفعل فئة جديدة. إذا أعطيت CustomErrorType نصًا ، حتى لو كان المنشئ لا يفعل شيئًا سوى استدعاء super () ، فسوف يعمل.

في حالة قيام شخص ما بإلقاء أي شيء مختلف عن فئة خطأ المثيل وكافح لاستخدام النصائح من هذا الموضوع (كما فعلت).
سيتحقق toThrow() القيمة التي يتم طرحها في حالة وجود فئة Error ، وإذا لم تكن كذلك - فلن يتم اكتشاف الرمية. لم يكن هذا واضحًا من المستندات والفطرة السليمة.
سيفشل هذا ، على الرغم من أنه يلقي بوضوح:

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toThrow()`

لكن هذا سيعمل (لست متأكدًا مما إذا كانت هناك طريقة أفضل):

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`

Karabur typo toBeThruthy يجب أن يكون toBeTruthy

إليك اختبارًا صريحًا يؤكد أنه سيتعطل بالتأكيد إذا لم يرمي ويطابق خطأ معينًا.

yourCoolAsyncMethod('yeah it is')
    .then(ok => { // Presumes not a Promise<void>
        expect(ok).toBeUndefined();
        done();
    })
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

مرحبًاSimenB.
إذا كان لدي هذا وهو يعمل.

async function check() {
    // do something
}
await expect(check()).rejects.toThrow(InternalServerErrorException);

يتم طرح InternalServerErrorException مع كائن ....

كيف يمكنني أيضًا تأكيد الخصائص عند الخطأ الذي تم إلقاؤه؟ على سبيل المثال:

  • استثناء.رسالة = "خطأ"
  • استثناء.الحالة = "500"

إليك اختبارًا صريحًا يؤكد أنه سيتعطل بالتأكيد إذا لم يرمي ويطابق خطأ معينًا.

yourCoolAsyncMethod('yeah it is')
    .then(ok => {
        expect(ok).toBeUndefined();
        done();
    })
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

المشكلة في هذا هي أن اختبارك سوف ينجح إذا لم يكن هناك أخطاء في الكود.

لذلك لن يقدم هذا الاختبار قيمة كبيرة حقًا لأن النتائج المتوقعة تتنوع بناءً على ما إذا كان الكود الذي يختبره به خطأ أم لا.

يجب أن تحتوي الاختبارات على تدفق سلبي أو إيجابي ويجب علينا اختبار ما هو مطلوب فقط للاختبار. هذا النوع من العشوائية ليس هو الأعظم.

يا @ ديفيد تينانت 🖐

شكرا لتوضيح ذلك. كنت أعمل على طريقة Promise<notVoid> في ذلك الوقت. أدركت أنني لم أشارك في حل مشترك صالح أيضًا لـ Promise<void> . قمت بتحديث إجابتي بتعليق يقول أنني وضعت افتراضات. أنا أتفق معك بشأن التدفق.

شكرا 💨

هوي futuredayv 👋

يا @ ديفيد تينانت 🖐

شكرا لتوضيح ذلك. كنت أعمل على طريقة Promise<notVoid> في ذلك الوقت. أدركت أنني لم أشارك في حل مشترك صالح أيضًا لـ Promise<void> . قمت بتحديث إجابتي بتعليق يقول أنني وضعت افتراضات. أنا أتفق معك بشأن التدفق.

شكرا 💨

المشكلة هي أن اختبارك سيستمر في النجاح إذا عاد الاختبار باطلاً. الذي يجب أن يكون خطأ صحيح؟
يعني استدعاء done() "اجتاز اختباري بالطريقة المتوقعة وأنا مستعد للانتقال إلى اختباري التالي"

yourCoolAsyncMethod('yeah it is')
     // -- Lets say your method does not throw, and returns void instead
    .then(ok => { // Presumes not a Promise<void>
        expect(ok).toBeUndefined(); // -- At this point if it was void, this would pass
        done(); // -- Then your test would end and the catch would not be reached
        // -- Now you have unknown behavior passing a test where it's suppose to catch a fail
    })
    .catch(bad => {
        // -- This block does not run because done() is called above
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

لست متأكدًا من الحل المناسب لحالة الاستخدام الخاصة بك. لكنني سأبدأ بعدم استدعاء done() في then أو ربما أترك خطأ في "then" للتأكد من فشل الاختبار ،

yourCoolAsyncMethod('yeah it is')
    .then(ok => throw new Error("This block of code should not be reached")
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

في حالة قيام شخص ما بإلقاء أي شيء مختلف عن فئة خطأ المثيل وكافح لاستخدام النصائح من هذا الموضوع (كما فعلت).
سيتحقق toThrow() القيمة التي يتم طرحها في حالة وجود فئة Error ، وإذا لم تكن كذلك - فلن يتم اكتشاف الرمية. لم يكن هذا واضحًا من المستندات والفطرة السليمة.
سيفشل هذا ، على الرغم من أنه يلقي بوضوح:

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toThrow()`

لكن هذا سيعمل (لست متأكدًا مما إذا كانت هناك طريقة أفضل):

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`

هناك طريقة أفضل قليلاً وهي استخدام toBeDefined() بدلاً من toBeTruthy() :
async function f() {throw 'aa'} const res = await expect(f()).rejects.toBeTruthy()`

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات