Jest: async/await toThrowκ°€ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

에 λ§Œλ“  2016λ…„ 09μ›” 15일  Β·  21μ½”λ©˜νŠΈ  Β·  좜처: facebook/jest

λ‹€μŒ ν…ŒμŠ€νŠΈ

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

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

μ‹€νŒ¨ν•˜κ³  였λ₯˜λ₯Ό μ œλŒ€λ‘œ ν¬μ°©ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€ (μ΅œμ‹  λ²„μ „μ˜ jestλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€)

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

λŒ€μ‹ μ—

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);
});

λ‹€μŒ 좜λ ₯κ³Ό ν•¨κ»˜ ν…ŒμŠ€νŠΈκ°€ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

ν•¨μˆ˜μ—μ„œ λ‹€μŒ μœ ν˜•μ˜ 였λ₯˜κ°€ λ°œμƒν•΄μ•Ό ν•©λ‹ˆλ‹€.
"μ‚¬μš©μž μ •μ˜ 였λ₯˜ μœ ν˜•"
ν•˜μ§€λ§Œ 아무것도 λ˜μ§€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ ν…ŒμŠ€νŠΈλŠ” μ‹€νŒ¨ν•˜μ§€λ§Œ λ˜μ Έμ§„ ν΄λž˜μŠ€κ°€ Error λ•Œ μ™„λ²½ν•˜κ²Œ μž‘λ™ν•©λ‹ˆλ‹€ . Error λ₯Ό ν™•μž₯ν•˜λ €κ³  ν•  λ•Œ
```μžλ°”μŠ€ν¬λ¦½νŠΈ
클래슀 CustomErrorType ν™•μž₯ 였λ₯˜ {}
````

그런 λ‹€μŒ 였λ₯˜λŠ”

ν•¨μˆ˜μ—μ„œ λ‹€μŒ μœ ν˜•μ˜ 였λ₯˜κ°€ λ°œμƒν•΄μ•Ό ν•©λ‹ˆλ‹€.
"μ‚¬μš©μž μ •μ˜ 였λ₯˜ μœ ν˜•"
λŒ€μ‹  λ‹€μŒμ„ λ˜μ‘ŒμŠ΅λ‹ˆλ‹€.
였λ₯˜

ν•΄λ‹Ή μƒ˜ν”Œμ—μ„œ 무엇이 잘λͺ»λ˜μ—ˆλŠ”지에 λŒ€ν•œ λ‹¨μ„œκ°€ μžˆμŠ΅λ‹ˆκΉŒ? λ‚˜λŠ” 농담 23.4.2λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

@Marchelune class CustomErrorType extends Error {} λ₯Ό μž‘μ„±ν•  λ•Œ μ‹€μ œλ‘œ μƒˆ 클래슀λ₯Ό μ •μ˜ν•˜μ§€ μ•Šμ€ κ²ƒμž…λ‹ˆλ‹€. CustomErrorType에 본문을 μ œκ³΅ν•˜λ©΄ super()λ₯Ό ν˜ΈμΆœν•˜λŠ” 것 μ™Έμ—λŠ” 아무것도 ν•˜μ§€ μ•ŠλŠ” μƒμ„±μžλΌλ„ μž‘λ™ν•©λ‹ˆλ‹€.

λˆ„κ΅°κ°€κ°€ μΈμŠ€ν„΄μŠ€ Error ν΄λž˜μŠ€μ™€ λ‹€λ₯Έ 것을 λ˜μ§€κ³  κ·Έ μŠ€λ ˆλ“œμ˜ 쑰언을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄ κ³ κ΅°λΆ„νˆ¬ν•˜λŠ” 경우 (λ‚΄κ°€ 그랬던 κ²ƒμ²˜λŸΌ).
toThrow() λŠ” Error 클래슀의 μΈμŠ€ν„΄μŠ€μΈ throw된 값을 ν™•μΈν•˜κ³  그렇지 μ•Šμ€ 경우 throwλ₯Ό κ°μ§€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이것은 λ¬Έμ„œμ™€ μƒμ‹μ—μ„œ λΆ„λͺ…ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.
λΆ„λͺ…νžˆ λ‹€μŒμ„ λ˜μ§€λ”λΌλ„ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

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 μ˜€νƒ€ 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();
    });

이것에 λŒ€ν•œ λ¬Έμ œλŠ” μ½”λ“œμ— 였λ₯˜κ°€ μ—†λŠ” 경우 ν…ŒμŠ€νŠΈλ₯Ό ν†΅κ³Όν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

λ”°λΌμ„œ 이 ν…ŒμŠ€νŠΈλŠ” ν…ŒμŠ€νŠΈ 쀑인 μ½”λ“œμ— 였λ₯˜κ°€ μžˆλŠ”μ§€ 여뢀에 따라 μ˜ˆμƒλ˜λŠ” κ²°κ³Όκ°€ λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— μ‹€μ œλ‘œ λ§Žμ€ κ°€μΉ˜λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

ν…ŒμŠ€νŠΈμ—λŠ” 음의 흐름 λ˜λŠ” μ–‘μ˜ 흐름이 μžˆμ–΄μ•Ό ν•˜λ©° ν…ŒμŠ€νŠΈμ— ν•„μš”ν•œ κ²ƒλ§Œ ν…ŒμŠ€νŠΈν•΄μ•Ό ν•©λ‹ˆλ‹€. 이런 μ’…λ₯˜μ˜ λ¬΄μž‘μœ„μ„±μ€ κ°€μž₯ 크지 μ•ŠμŠ΅λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš” @David-Tennant πŸ–

μ§€μ ν•΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. κ·Έ λ‹Ήμ‹œ λ‚˜λŠ” Promise<notVoid> λ°©μ‹μœΌλ‘œ μž‘μ—…ν•˜κ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€. Promise<void> 에도 μœ νš¨ν•œ 곡톡 μ†”λ£¨μ…˜μ„ κ³΅μœ ν•˜μ§€ μ•Šμ•˜λ‹€λŠ” 것을 κΉ¨λ‹¬μ•˜μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 가정을 λ§Œλ“€μ—ˆλ‹€λŠ” 의견으둜 닡변을 μ—…λ°μ΄νŠΈν–ˆμŠ΅λ‹ˆλ‹€. 흐름에 λŒ€ν•΄μ„œλŠ” λ™μ˜ν•©λ‹ˆλ‹€.

κ°μ‚¬ν•©λ‹ˆλ‹€ πŸ’¨

μ•ˆλ…• @futuredayv πŸ‘‹

μ•ˆλ…•ν•˜μ„Έμš” @David-Tennant πŸ–

μ§€μ ν•΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. κ·Έ λ‹Ήμ‹œ λ‚˜λŠ” 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 μ•„λ‹ˆλ©΄ 확인 ν…ŒμŠ€νŠΈκ°€ μ‹€νŒ¨ ν™•μΈν•˜κΈ° μœ„ν•΄ "λ‹€μŒ"μ—μ„œ 였λ₯˜λ₯Ό λ˜μ§€κ³ ,

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();
    });

λˆ„κ΅°κ°€κ°€ μΈμŠ€ν„΄μŠ€ Error ν΄λž˜μŠ€μ™€ λ‹€λ₯Έ 것을 λ˜μ§€κ³  κ·Έ μŠ€λ ˆλ“œμ˜ 쑰언을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄ κ³ κ΅°λΆ„νˆ¬ν•˜λŠ” 경우 (λ‚΄κ°€ 그랬던 κ²ƒμ²˜λŸΌ).
toThrow() λŠ” Error 클래슀의 μΈμŠ€ν„΄μŠ€μΈ throw된 값을 ν™•μΈν•˜κ³  그렇지 μ•Šμ€ 경우 throwλ₯Ό κ°μ§€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이것은 λ¬Έμ„œμ™€ μƒμ‹μ—μ„œ λΆ„λͺ…ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.
λΆ„λͺ…νžˆ λ‹€μŒμ„ λ˜μ§€λ”λΌλ„ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

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 λ“±κΈ‰