BlogFlow | 블로그

프론트엔드 개발과 IT 기술을 중심으로 실무 경험과 학습을 기록합니다.

프로그래밍

Jest에서 mockImplementation으로 try, catch문에서 console.error 검증 방법

2026.02.02·약 7분

이 글에서 정리하는 내용

이 글은 Jest 테스트에서 try / catch로 처리된 에러가 왜 실패로 인식되지 않는지 설명하고, 에러를 던지지 않는 구조에서 console.error 호출 여부로 오류를 검증하는 실무 테스트 패턴을 정리합니다. 개별 개념을 잘게 나누기보다, 테스트 관점에서 문제가 발생하는 지점과 이를 해결하는 전략을 하나의 흐름으로 묶어 설명합니다.

try / catch 구조에서 테스트가 실패하지 않는 이유

ChatGPT Image 2026년 2월 2일 오후 03 37 01 1

테스트는 통과하지만 실제로는 에러가 발생하는 상황

테스트를 작성하다 보면 코드 내부에서 분명 오류가 발생했는데도 Jest 테스트는 정상적으로 통과하는 상황을 마주하게 됩니다. 특히 try / catch 내부에서 에러를 잡고 console.error만 호출하는 구조에서는 이 문제가 더욱 명확하게 드러납니다.

try {
  // 올바른 코드
} catch (error) {
  console.error(error);
}

이 구조에서는 에러가 발생하더라도 throw되지 않기 때문에 Jest는 테스트를 실패로 판단하지 않습니다.

이 코드에서 오류가 발생하면 콘솔에는 에러 로그가 남지만, 테스트 자체는 실패하지 않습니다. 겉보기에는 아무 문제가 없는 테스트처럼 보이기 때문에 실제 오류를 놓치기 쉽습니다.

Jest가 테스트 실패를 판단하는 기준

Jest는 기본적으로 테스트 실행 중 throw된 에러만을 실패 조건으로 인식합니다. 에러가 발생하더라도 코드 흐름 안에서 잡혀버리면 Jest 입장에서는 정상 종료로 판단합니다.

console.error, console.warn와 같은 로그 출력은 테스트 실패 여부와 직접적인 연관이 없습니다. 따라서 에러를 출력만 하고 던지지 않는 구조에서는 Jest가 문제를 감지하지 못합니다.

try / catch + console.error 구조의 테스트 한계

방어 코드나 공통 유틸리티에서는 에러를 상위로 던지지 않고 내부에서 처리하는 경우가 많습니다. 이 패턴은 런타임 안정성 측면에서는 유리하지만, 테스트 관점에서는 에러가 발생했다는 사실 자체가 사라지는 문제가 생깁니다.

console.error를 검증 대상으로 만드는 전략

에러를 던지지 않는 구조에서의 테스트 접근

이 문제를 해결하기 위한 핵심 아이디어는 에러를 억지로 던지는 것이 아니라, 에러가 발생했다는 흔적을 테스트의 검증 대상으로 삼는 것입니다.

console.error는 에러 발생 시 반드시 호출되는 지점이므로, 이 호출 여부를 기준으로 테스트를 구성하면 try / catch 구조를 유지한 채 오류 상황을 검증할 수 있습니다.

jest.spyOn + mockImplementation 패턴

Jest에서는 jest.spyOn을 사용해 특정 객체의 메서드를 가로챌 수 있습니다. 여기에 mockImplementation을 함께 사용하면 실제 콘솔 출력은 막고, 호출 여부만 추적할 수 있습니다.

jest.spyOn(console, 'error').mockImplementation(() => {});

이 코드는 실제 콘솔 출력은 막되, console.error가 호출되었는지는 테스트에서 검증할 수 있게 만듭니다.

이 방식은 테스트 로그를 깨끗하게 유지하면서도, 에러 발생 여부를 명확하게 검증할 수 있다는 장점이 있습니다.

공통 테스트 설정 패턴

beforeEach / afterEach로 구조 정리하기

모든 테스트가 try / catch 기반 로직을 다룬다면, 매 테스트마다 spy를 설정하는 것은 비효율적입니다. 이 경우 beforeEachafterEach를 활용한 공통 설정이 적합합니다.

beforeEach(() => {
  jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
  jest.restoreAllMocks();
});

beforeEach에서는 원본 console.error를 가로채고, afterEach에서는 모든 mock을 복구합니다. 이를 통해 테스트 간 호출 누적을 방지하고, 항상 동일한 테스트 환경을 유지할 수 있습니다.

이 방식의 적용 기준과 정리

언제 유효하고, 언제 주의해야 하는가

이 패턴은 공통 유틸 함수, 포맷터, 방어 로직처럼 에러를 외부로 던지지 않는 구조에서 특히 유용합니다. 반대로 비즈니스 로직의 핵심 에러까지 모두 삼켜버리는 구조라면 설계 자체를 다시 검토해야 합니다. 테스트 편의를 위해 핵심 에러까지 삼키는 구조라면, 테스트 문제가 아니라 설계 문제일 가능성이 큽니다.

정리

Jest 테스트에서 통과 여부만으로 코드의 안정성을 판단하는 것은 위험할 수 있습니다. console.error를 검증 대상으로 삼는 패턴은 try / catch 구조가 가진 테스트상의 맹점을 보완하며, 실제 런타임 동작과 테스트 검증 사이의 간극을 메워주는 실무적인 방법입니다.

FAQ

Q. console.error 대신 에러를 throw하면 안 되나요?
에러를 상위로 던져야 하는 로직이라면 throw가 더 명확합니다. 다만 공통 유틸이나 방어 로직에서는 런타임 안정성을 위해 catch 후 처리하는 경우가 많아, 이때는 spy 기반 검증이 적합합니다.

Q. console.warn도 같은 방식으로 테스트할 수 있나요?
가능합니다. console.warn, console.info 등도 동일하게 jest.spyOn으로 가로채 테스트할 수 있습니다.

Q. spy를 전역으로 설정해도 괜찮나요?
반드시 afterEach에서 jest.restoreAllMocks()를 호출해 원복해야 합니다. 그렇지 않으면 테스트 간 영향이 누적될 수 있습니다.

Q. 면접에서 이런 테스트 패턴을 설명해도 되나요?
Jest의 실패 판단 기준과 try / catch 구조의 한계를 함께 설명할 수 있다면, 테스트에 대한 이해도를 보여주는 좋은 사례가 될 수 있습니다.

이 글이 마음에 드세요?

RSS 피드를 구독하세요!

댓글 남기기