2026년 상식닷컴 선정 식당 & 카페 리스트
최근에 오픈한 호텔을 찾는다면 살펴보세요

JUnit에서 외부 API를 mocking 하는 방법은?

_____
Q1: JUnit에서 외부 API를 mocking 하는 기본적인 방법은 무엇인가요?
A1: JUnit 자체는 mocking 기능을 제공하지 않으므로, Mockito, EasyMock, WireMock 등 별도의 mocking 라이브러리를 사용합니다. 일반적으로 Mockito를 많이 사용하며, 테스트 대상 클래스에 주입된 외부 API 호출 객체(예: RestTemplate, WebClient 등)를 Mockito의 `@Mock` 또는 `mock()` 메서드로 mocking 하고, 해당 객체의 API 호출 반환값을 `when(...).thenReturn(...)` 형태로 지정하여 외부 호출을 흉내냅니다.

---

Q2: Mockito를 사용해 REST API 호출을 mocking 하는 예시를 보여주세요.
A2: 예를 들어, `RestTemplate`을 사용하는 서비스에서 외부 API를 mocking 하는 기본 코드는 다음과 같습니다.

```java
@ExtendWith(MockitoExtension.class)
class MyServiceTest {

@Mock
private RestTemplate restTemplate;

@InjectMocks
private MyService myService; // RestTemplate을 주입받는 서비스

@Test
void testExternalApiCall() {
String mockResponse = "{\"data\":\"value\"}";
ResponseEntity responseEntity = new ResponseEntity<>(mockResponse, HttpStatus.OK);

when(restTemplate.getForEntity("https://external.api/data", String.class))
.thenReturn(responseEntity);

String result = myService.callExternalApi();

assertEquals("value", result);
}
}
```

---

Q3: WireMock은 무엇이고, 어느 상황에서 사용하나요?
A3: WireMock은 외부 HTTP API를 로컬 HTTP 서버로 시뮬레이션 하는 도구입니다. 실제로 HTTP 요청을 보내고 응답을 받는 구조를 테스트하고 싶을 때 유용하며, REST 서버 스텁 서버를 실행하여 외부 API를 완전히 대체합니다. 복잡한 API 응답을 시뮬레이션하거나 통합 테스트에 적합합니다.

---

Q4: WireMock을 JUnit 테스트에 적용하는 기본 방법은?
A4: WireMock 라이브러리를 테스트 의존성에 추가 후, `@Rule` 또는 JUnit5에서는 `@RegisterExtension` 을 사용하여 WireMock 서버를 실행하고, 특정 API 요청에 대해 스텁(Stub)을 등록합니다. 예시는 다음과 같습니다.

```java
@ExtendWith(WireMockExtension.class)
class MyServiceTest {

@RegisterExtension
static WireMockExtension wireMock = WireMockExtension.newInstance()
.options(wireMockConfig().dynamicPort())
.build();

@Test
void testWireMock() {
wireMock.stubFor(get(urlEqualTo("/data"))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withBody("{\"data\":\"value\"}")));

MyService service = new MyService("http://localhost:" + wireMock.getPort());
String result = service.callExternalApi();

assertEquals("value", result);
}
}
```

---

Q5: 외부 API mocking 시 주의할 점은 무엇인가요?
A5:
- 실제 API와 응답 형태가 일치하도록 mock 데이터를 만들어야 하며, 실제와 다른 데이터를 쓰면 테스트 신뢰도가 떨어집니다.
- 네트워크 환경, 인증, 타임아웃 등도 고려되어야 하므로 mocking 범위와 테스트 목적을 명확히 해야 합니다.
- 너무 많은 mocking은 실제 통합 환경과 달라질 수 있으므로, 단위 테스트용 mocking과 통합 테스트의 적절한 분리를 권장합니다.
- Mockito 등으로 내부 호출만 mocking 하면 외부 시스템 의존성은 줄지만, API 계약이 변경되었을 때 미리 발견하기 어려울 수도 있습니다.

---

Q6: WebClient를 mocking 하고 싶으면 어떻게 해야 하나요?
A6: WebClient는 내부적으로 비동기 및 리액티브 구조를 가지므로 직접 mocking 방법이 복잡할 수 있습니다. 주로 `WebClient.Builder`를 mocking 하거나, `exchangeToMono`, `retrieve` 메서드를 Mockito로 mocking 하여 반환값을 지정합니다. 또는 WebClient를 사용하는 Repository나 Service 계층을 분리하여 해당 계층을 mocking 하는 방법도 많이 사용됩니다.

---

Q7: 테스트 코드에서 mocking이 어려운 경우 대체 방안은?
A7: 외부 API를 통째로 mocking 하기 힘들다면 다음 방법이 있습니다.
- 계약 테스트(Consumer Driven Contract) 사용: PACT, Spring Cloud Contract 등으로 API 계약을 명시하고 검증
- 테스트 전용 API 서버 구축 또는 WireMock 등 HTTP 스텁서버 운영
- 테스트 환경에서 실제 API 대신 샌드박스/테스트 API 서버 연동
- API 클라이언트 추상화 후 인터페이스 mocking

---

요약: JUnit에서는 Mockito 같은 mocking 라이브러리로 REST 호출 객체를 mocking하거나, WireMock으로 외부 API를 HTTP 스텁 서버로 대체하여 외부 API 호출을 모방합니다. 테스트 목적과 환경에 따라 적절한 방법을 선택해 적용하는 것이 중요합니다.
JUnit에서 외부 API를 mocking 하는 방법에 대해 설명드리겠습니다.

외부 API를 직접 호출하면 테스트가 느려지고 불안정해질 수 있기 때문에, 실제 호출을 막고 예상 응답을 반환하도록 mocking 하는 것이 일반적입니다.

대표적으로 사용하는 도구는 Mockito, WireMock, MockWebServer 등이 있으며, 상황에 따라 적합한 방법을 선택할 수 있습니다.

1. Mockito를 이용한 API 클라이언트 mocking - 개념 : 외부 API 호출을 담당하는 클라이언트(예: RestTemplate, WebClient, FeignClient)를 Mockito로 mocking 하여, 실제 네트워크 호출 없이 미리 정의한 응답을 반환하게 합니다.

- 방법 : 1. 외부 API 호출 로직이 포함된 클래스나 메서드를 테스트 대상 클래스에 주입(injection)할 수 있어야 합니다.



2. 테스트 클래스에서 Mockito의 `@Mock` 또는 `Mockito.mock()`으로 API 호출 객체를 생성합니다.



3. `when(...).thenReturn(...)`으로 호출 결과를 미리 정의합니다.



4. 테스트 대상 클래스에 mock 객체를 주입해 외부 호출 대신 mocking 된 응답이 사용되도록 합니다.

- 예 : ```java @ExtendWith(MockitoExtension.class) public class MyServiceTest { @Mock private RestTemplate restTemplate; @InjectMocks private MyService myService; // 실제로 외부 API 호출하는 서비스 @Test public void testExternalApiCall() { String url = "http://external.api/resource"; ResponseEntity mockResponse = new ResponseEntity<>("mocked response", HttpStatus.OK); when(restTemplate.getForEntity(url, String.class)).thenReturn(mockResponse); String result = myService.callExternalApi(); assertEquals("mocked response", result); } } ``` - 장점 : 코드 레벨에서 세밀한 동작 제어 가능, 별도의 서버가 필요 없음. - 단점 : 외부 API의 HTTP 레벨 동작(헤더, 바디, 실제 요청 등)은 검증 어려움. ---

2. WireMock을 이용한 HTTP 서버 mocking - 개념 : WireMock은 로컬에 가벼운 HTTP 서버(mock server)를 띄워서, 외부 API의 HTTP 요청을 받고 미리 설정한 응답을 반환하도록 설정할 수 있습니다.

- 방법 : 1. WireMock을 테스트에 포함시키고 테스트 시작 시 mock 서버를 실행합니다.



2. WireMock API를 사용해 특정 HTTP 요청에 대한 예상 응답을 설정합니다.



3. 외부 API 호출이 실제 WireMock 서버 주소로 향하게 설정합니다.



4. 테스트 종료 시 mock 서버를 중지합니다.

- 예 : ```java @ExtendWith(WireMockExtension.class) public class MyServiceTest { @RegisterExtension static WireMockExtension wireMock = WireMockExtension.newInstance() .options(options().port(808

9)) .build(); @InjectMocks private MyService myService; // 외부 API endpoint를 localhost:8089로 설정했다고 가정 @Test public void testApiCall() { wireMock.stubFor(get(urlEqualTo("/resource")) .willReturn(aResponse() .withStatus(200) .withBody("mocked response"))); String result = myService.callExternalApi(); assertEquals("mocked response", result); } } ``` - 장점 : 실제 HTTP 통신을 테스트할 수 있어 API의 REST 스펙 검증에 유리. - 단점 : 테스트 환경 구축이 복잡할 수 있고, 테스트 속도가 약간 느릴 수 있음. ---

3. MockWebServer (OkHttp) 활용 - 개념 : MockWebServer는 OkHttp에서 제공하는 HTTP mock 서버로, WireMock보다 가볍고 테스트 내 단기간 실행에 적합합니다.

- 방법 : 1. 테스트 내에서 MockWebServer를 시작합니다.



2. API 응답을 enqueue하여 사전 정의합니다.



3. 테스트 대상 클래스가 MockWebServer 주소로 호출하도록 설정합니다.



4. 테스트 후 서버 종료. - 예 : ```java public class MyServiceTest { private MockWebServer mockWebServer; private MyService myService; @BeforeEach public void setup() throws IOException { mockWebServer = new MockWebServer(); mockWebServer.start(); String baseUrl = mockWebServer.url("/").toString(); myService = new MyService(baseUrl); } @AfterEach public void tearDown() throws IOException { mockWebServer.shutdown(); } @Test public void testApiCall() throws InterruptedException { mockWebServer.enqueue(new MockResponse() .setResponseCode(200) .setBody("mocked response")); String result = myService.callExternalApi(); assertEquals("mocked response", result); RecordedRequest request = mockWebServer.takeRequest(); assertEquals("/resource", request.getPath()); } } ``` - 장점 : 매우 경량, 네트워크 통신 흐름 및 요청 검증 가능.

- 단점 : OkHttp 기반 통신에 좀 더 적합. --- 정리 - Mockito : 코드 레벨에서 간단히 외부 API 호출 모킹. 네트워크 동작 검증 필요 없을 때 적합. - WireMock : 복잡한 HTTP 상호작용을 통합 테스트로 검증할 때 적합, 실제 서버를 띄움. - MockWebServer : 가벼운 HTTP mock 서버, OkHttp 기반 호출에 적합. 상황과 요구사항에 따라 적합한 방식을 선택해 JUnit 테스트 환경 내에서 외부 API 호출을 안정적으로 mocking 하실 수 있습니다.

작성자: 정재훈 [비회원] | 작성일자: 1년 전 2025-05-26 02:51:06
조회수: 202 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
내용이 부정확하다면 싫어요를 클릭해주세요.