Jest에서 커스텀 매처에 대한 테스트 작성

TLDR: 다음은 맞춤 매처에 대한 테스트를 작성하는 방법의 예입니다.

describe("toHaveDevDependency", () => {
  it("fails when given a number", () => {
    expect(() => {
      expect(2).toHaveDevDependency("node");
    }).toThrow("Expected 2 to be a YeomanTest.RunResult");
  );
});


동기 부여



TDD 의 정신으로 Jest 사용자 지정 매처가 제대로 작동하는지 확인하는 테스트를 작성하고 싶었습니다.

"맞춤 매처에 대한 Jest 쓰기 테스트"에 대한 빠른 Google 검색은 내 맞춤 매처를 실행하는 테스트를 작성하는 방법의 예를 실제로 보고 싶었을 때 맞춤 매처 자체 작성에 대한 결과만 생성했습니다.

이 작업을 스스로 수행하는 방법을 알아낸 후 누락된 기사를 작성해야겠다고 생각했습니다 :).

배경



Jest 에 익숙하다면 custom matchers 도 익숙할 것입니다.

그렇지 않은 경우 요약 버전은 다음과 같습니다. 사용자 지정 매처를 사용하면 expect 문에 대해 일치하는 어설션을 추가할 수 있습니다. 이는 동일한 테스트 코드를 반복해서 작성하고 테스트를 DRY하고 싶을 때 매우 유용할 수 있습니다.

예시 상황



이것은 최근에 새 프로젝트를 신속하게 스캐폴드하기 위해 Yeoman generator을 작성할 때 발생했습니다. 프로젝트와 함께 생성된 expect(result).toHaveDevDependency("typescript") 파일이 package.json 에 지정된 패키지를 포함한다고 주장하기 위해 devDependencies 과 같은 것을 작성하고 싶었습니다.

Yeoman이 yeoman-test 에서 제공한 테스트 도우미에는 유용한 assertJsonFileContent(fileName: string, content: any) 메서드가 포함되어 있지만

result.assertJsonFileContent(
  "package.json",
  { 
    devDependencies: {
      typescript: "4.7.4"
    }
  },
);


계속해서 나는 장황함에 싫증이 났고 이 줄이 가능한 한 명확하게 내 의도를 나타내지 않는다는 것을 깨달았습니다.

대신 다음과 같은 것을 원했습니다.

expect(result).toHaveDevDependency("typescript", "4.7.4");


간단하고 명확하며 깨끗합니다.

toHaveDevDependency 사용자 지정 매처는 expect 호출에서 수신된 개체가 실제로 YeomanTest.RunResult 개체인지 확인하는 검사를 포함하여 합리적으로 복잡해졌습니다. 그런 다음 result.assertJsonFileContent() 호출을 try/catch으로 래핑하여 해당 결과를 통과 또는 유용한 메시지와 함께 jest.CustomMatcherResult 실패.

아이러니하게도 사용자 정의 매처는 내 코드 베이스에서 가장 적게 테스트된 부분으로 내 코드 커버리지 보고서에 표시되었습니다.

해결책



나는 toHaveDevDependency에 대한 테스트 스위트를 작성했고 그 과정에서 expect 문 자체를 테스트하는 방법을 알아내야 했습니다. 오히려 메타.

첫 번째 시도: try/catch에서 예상 호출을 래핑합니다.



내 첫 번째 시도는 다음과 같습니다.

describe("toHaveDevDependency", () => {
  it("fails when given a number", () => {
    try {
      expect(2).toHaveDevDependency("node");
    } catch (error) {
      expect(error.message).toContain("JestAssertionError");
    }
  );
});

expect 어설션이 실패할 때 Jest가 어떤 종류의 오류를 던질 가능성이 있고 아마도 내가 그 오류를 잡아서 뭔가를 할 수 있을 것이라는 생각입니다.

불행히도 이것은 작동하지 않습니다. Jest는 테스트를 즉시 실패할 만큼 똑똑한 것 같고 오류를 잡을 수는 있지만 이 경로에서 테스트 실패를 막을 수 있는 쉬운 방법을 찾지 못했습니다. 방법이 있을지도 모르지만 찾기 전에 포기했습니다.

두 번째 시도: expect().toThrow()로 원시 예상 호출을 래핑합니다.



다음 아이디어는 expect().toThrow() 메서드를 사용하여 Jest에게 오류 발생을 예상하고 있음을 명시적으로 알리는 것이었습니다. 다음과 같이 생겼습니다.

describe("toHaveDevDependency", () => {
  it("fails when given a number", () => {
    expect(
      expect(2).toHaveDevDependency("node");
    ).toThrow("Expected 2 to be a YeomanTest.RunResult");
  );
});


이것도 작동하지 않았습니다. 테스트는 즉시 실패했습니다.

최종 작업 시도: 예상 호출을 화살표 함수로 래핑하고 이를 expect().toThrow()로 래핑합니다.



한 가지 아이디어가 더 있습니다. 먼저 expect 호출을 화살표 함수로 래핑하면 어떻게 될까요?

이것은 다음과 같이 보였다:

describe("toHaveDevDependency", () => {
  it("fails when given a number", () => {
    expect(() => {
      expect(2).toHaveDevDependency("node");
    }).toThrow("Expected 2 to be a YeomanTest.RunResult");
  );
});


작동합니다! 정확한 이유를 이해할 만큼 충분히 Jest 내부를 들여다보지는 않았지만 직관적으로 이것은 의미가 있습니다. 화살표 함수는 Jest 테스트 컨텍스트에서 expect에 대한 내부 호출을 격리하고 함수 호출이 it 블록 내에서 즉시 실행되는 것을 방지합니다.

이제 맞춤 매처용 테스트 스위트를 즐겁게 작성하고 자신 있게 모든 것을 테스트할 수 있습니다!

좋은 웹페이지 즐겨찾기