Jest에서 발생하는 예외 유형을 테스트하는 방법


161

함수에 의해 throw 된 예외 유형을 테스트 해야하는 코드를 사용하고 있습니다 (TypeError, ReferenceError 등).

현재 테스트 프레임 워크는 AVA이며 다음과 같이 두 번째 인수 t.throws방법 으로 테스트 할 수 있습니다.

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  t.is(error.message, 'UNKNOWN ERROR');
});

Jest에 테스트를 다시 작성하기 시작했으며 쉽게 수행하는 방법을 찾지 못했습니다. 가능합니까?

답변:


225

Jest에서는 함수를 expect (function) .toThrow (공백 또는 오류 유형)에 전달해야합니다.

예:

test("Test description", () => {
  const t = () => {
    throw new TypeError();
  };
  expect(t).toThrow(TypeError);
});

기존 함수가 인수 세트로 처리되는지 여부를 테스트해야하는 경우 expect ()의 익명 함수로 랩핑해야합니다.

예:

test("Test description", () => {
  expect(() => {http.get(yourUrl, yourCallbackFn)}).toThrow(TypeError);
});

79

조금 이상하지만 작동하지만 imho는 읽기 쉽습니다.

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
  try {
      throwError();
      // Fail test if above expression doesn't throw anything.
      expect(true).toBe(false);
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

Catch블록 예외를 잡으면 제기 된 테스트 할 수 있습니다 Error. 이상한이 expect(true).toBe(false);예상되는 경우 테스트에 실패 할 필요가 Error발생되지 않습니다. 그렇지 않으면이 라인에 도달 할 수 없습니다 ( Error앞에 제기해야 함).

편집 : @ Kenny Body는 사용하면 코드 품질을 향상시키는 더 나은 솔루션을 제안합니다 expect.assertions()

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
  expect.assertions(1);
  try {
      throwError();
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

자세한 설명과 함께 원래 답변을 참조하십시오 : Jest에서 예외 유형을 테스트하는 방법


18
이것은 Jest가 이미 예외를 검사하는 expect.toThrow () 방법을 가지고있을 때 예외를 테스트하는 매우 장황한 방법입니다. jestjs.io/docs/en/expect.html#tothrowerror
gomisha

4
예, 그러나 메시지 또는 다른 내용이 아닌 유형 만 테스트하고 질문은 유형이 아닌 테스트 메시지에 관한 것입니다.
bodolsog

2
하 내 코드가 던져진 오류 값을 테스트해야하므로 인스턴스가 필요하므로 실제로이 것과 같습니다. 나는 expect('here').not.toBe('here');그것의 재미를 위해서 처럼 잘못된 기대를 쓸 것이다. :-)
Valery

4
@Valery 또는 : expect('to be').not.toBe('to be')셰익스피어 스타일.
Michiel van der Blonk

2
가장 과소 평가 된 답변!
Edwin Ikechukwu Okonkwo

41

약간 더 간결한 버전을 사용합니다.

expect(() => {
  //code block that should throw error
}).toThrow(TypeError) //or .toThrow('expectedErrorMessage')

2
짧고 정확합니다.
flapjack

33

Jest에 대한 (제한적이지만) 노출 expect().toThrow()에서 특정 유형의 오류가 발생했는지 테스트하려는 경우에 적합한 것으로 나타났습니다 .

expect(() => functionUnderTest()).toThrow(TypeError);

또는 특정 메시지와 함께 오류가 발생합니다.

expect(() => functionUnderTest()).toThrow('Something bad happened!');

둘 다하려고하면 오 탐지를 얻게됩니다. 예를 들어 코드가 throw RangeError('Something bad happened!')되면이 테스트는 다음을 통과합니다.

expect(() => functionUnderTest()).toThrow(new TypeError('Something bad happened!'));

시도를 사용하여 제안 bodolsog에 의한 대답은 / 캐치 대신 사용할 수있는, 가까운, 오히려 사실 기대보다가 캐치의 주장이 충돌하는 기대 보장하기 위해 허위로 expect.assertions(2)테스트의 시작에 2기대 주장의 수는 . 나는 이것이 테스트의 의도를보다 정확하게 설명한다고 생각합니다.

오류의 유형 및 메시지를 테스트하는 전체 예 :

describe('functionUnderTest', () => {
    it('should throw a specific type of error.', () => {
        expect.assertions(2);

        try {
            functionUnderTest();
        } catch (error) {
            expect(error).toBeInstanceOf(TypeError);
            expect(error).toHaveProperty('message', 'Something bad happened!');
        }
    }); 
});

functionUnderTest()오류가 발생하지 않으면 어설 션이 적중되지만 expect.assertions(2)테스트는 실패하고 테스트는 실패합니다.


도 나는 항상 Jest의 다중 어설 션 기능을 기대하는 것을 잊어 버린다.
kpollock

이것은 나를 위해 완벽하게 작동했습니다. 사용해야합니다.
Ankit Tanna

expect.hasAssertions()테스트에 어설 션 catch이없는 경우 어설 션을 추가 / 제거 할 경우 번호를 업데이트 할 필요 가 없으므로 더 나은 대안이 될 수 있습니다.
André Sassi

12

직접 시도하지는 않았지만 Jest의 toThrow 어설 션을 사용하는 것이 좋습니다 . 따라서 귀하의 예는 다음과 같이 보일 것입니다.

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  expect(t).toThrowError('UNKNOWN ERROR');
  //or
  expect(t).toThrowError(TypeError);
});

다시 테스트하지는 않았지만 제대로 작동한다고 생각합니다.


8

Jest에는 toThrow(error)함수가 호출 될 때 발생하는지 테스트 하는 메소드 가 있습니다.

따라서 귀하의 경우에는 다음과 같이 전화해야합니다.

expect(t).toThrowError(TypeError);

문서


1
jest.spyOn(service, 'create').mockImplementation(() => { throw new Error(); });mocked 메소드 create가 아닌 경우에는 작동 하지 않습니다 async.
Sergey

7

현대식 농담을 사용하면 거부 된 가치를 더 많이 확인할 수 있습니다. 예를 들면 다음과 같습니다.

const request = Promise.reject({statusCode: 404})
await expect(request).rejects.toMatchObject({ statusCode: 500 });

오류와 함께 실패합니다

Error: expect(received).rejects.toMatchObject(expected)

- Expected
+ Received

  Object {
-   "statusCode": 500,
+   "statusCode": 404,
  }

6

문서는 이 작업을 수행하는 방법에 분명하다. 두 개의 매개 변수를 취하는 함수가 있는데 그 중 하나가 인 경우 오류가 발생한다고 가정 해 봅시다 null.

function concatStr(str1, str2) {
  const isStr1 = str1 === null
  const isStr2 = str2 === null
  if(isStr1 || isStr2) {
    throw "Parameters can't be null"
  }
  ... // continue your code

당신의 시험

describe("errors", () => {
  it("should error if any is null", () => {
    // notice that the expect has a function that returns the function under test
    expect(() => concatStr(null, "test")).toThrow()
  })
})

4

Promises 로 작업하는 경우 :

await expect(Promise.reject(new HttpException('Error message', 402)))
  .rejects.toThrowError(HttpException);

시간을 절약 해 주셔서 감사합니다 !!
Aditya Kresna Permana

3

테스트 유틸리티 라이브러리를위한 편리한 방법을 작성했습니다.

/**
 *  Utility method to test for a specific error class and message in Jest
 * @param {fn, expectedErrorClass, expectedErrorMessage }
 * @example   failTest({
      fn: () => {
        return new MyObject({
          param: 'stuff'
        })
      },
      expectedErrorClass: MyError,
      expectedErrorMessage: 'stuff not yet implemented'
    })
 */
  failTest: ({ fn, expectedErrorClass, expectedErrorMessage }) => {
    try {
      fn()
      expect(true).toBeFalsy()
    } catch (err) {
      let isExpectedErr = err instanceof expectedErrorClass
      expect(isExpectedErr).toBeTruthy()
      expect(err.message).toBe(expectedErrorMessage)
    }
  }

Jests 자체 기능을 사용하여 동일한 작업을 수행 할 수 있습니다. -이 작업을 수행 할 수있는 방법에 대한 내 대답을 참조하십시오 stackoverflow.com/a/58103698/3361387
케니 바디

3

Peter Danis의 게시물에 덧붙여 "함수를 함수 (passive)에 전달 (공백) .toThrow (공백 또는 에러 유형)")과 관련된 솔루션의 일부를 강조하고 싶었습니다.

Jest에서 오류가 발생 해야하는 경우를 테스트 할 때 테스트중인 함수의 expect () 줄 바꿈 내에서 작동하려면 화살표 함수 줄 바꿈 레이어를 하나 더 제공해야합니다. 즉

잘못됨 (그러나 대부분의 사람들의 논리적 접근 방식) :

expect(functionUnderTesting();).toThrow(ErrorTypeOrErrorMessage);

권리:

expect(() => { functionUnderTesting(); }).toThrow(ErrorTypeOrErrorMessage);

매우 이상하지만 테스트를 성공적으로 실행해야합니다.


1

시험
expect(t).rejects.toThrow()


4
try? 시도는 없지만 대답합니다. 이것이 답이라면 더 자세히 설명하십시오. 기존 답변에 무엇을 추가합니까?
dWinder

7
@Razim은 시도 캐치를 사용하지 말고 솔루션을 시도해야한다고 말하고 있다고 생각합니다.
Tom
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.