Mocking a RestTemplate in Spring

Dev.Hammy·2024년 4월 1일

Mockito_Tutorial

목록 보기
18/21

1. Introduction

우리는 일종의 웹 요청을 수행하는 애플리케이션을 자주 사용합니다. 이 동작을 테스트할 때 Spring 앱에는 몇 가지 옵션이 있습니다.

이 빠른 튜토리얼에서는 RestTemplate을 통해서만 수행되는 호출을 mocking하는 몇 가지 방법을 살펴보겠습니다.

인기 있는 모의 라이브러리인 Mockito로 테스트부터 시작하겠습니다. 그런 다음 서버 상호 작용을 정의하기 위해 모의 서버를 생성하는 메커니즘을 제공하는 Spring Test를 사용합니다.

Using Mockito

Mockito를 사용하여 RestTemplate을 완전히 모의할 수 있습니다. 이 접근 방식을 사용하면 서비스 테스트가 모의 작업과 관련된 다른 테스트만큼 간단해집니다.

HTTP를 통해 직원 세부 정보를 가져오는 간단한 EmployeeService 클래스가 있다고 가정해 보겠습니다.

@Service
public class EmployeeService {
    
    @Autowired
    private RestTemplate restTemplate;

    public Employee getEmployee(String id) {
	ResponseEntity resp = 
          restTemplate.getForEntity("http://localhost:8080/employee/" + id, Employee.class);
        
	return resp.getStatusCode() == HttpStatus.OK ? resp.getBody() : null;
    }
}

이제 이전 코드에 대한 테스트를 구현해 보겠습니다.

@ExtendWith(MockitoExtension.class)
public class EmployeeServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private EmployeeService empService = new EmployeeService();

    @Test
    public void givenMockingIsDoneByMockito_whenGetIsCalled_shouldReturnMockedObject() {
        Employee emp = new Employee(“E001”, "Eric Simmons");
        Mockito
          .when(restTemplate.getForEntity(
            "http://localhost:8080/employee/E001", Employee.class))
          .thenReturn(new ResponseEntity(emp, HttpStatus.OK));

        Employee employee = empService.getEmployee(id);
        Assertions.assertEquals(emp, employee);
    }
}

위의 JUnit 테스트 클래스에서는 먼저 Mockito에게 @Mock 어노테이션을 사용하여 더미 RestTemplate 인스턴스를 생성하도록 요청했습니다.

그런 다음 EmployeeService 인스턴스에 @InjectMocks 어노테이션을 달아 더미 인스턴스를 주입했습니다.

마지막으로 테스트 메서드에서 Mockito의 when/then 지원을 사용하여 모의 동작을 정의했습니다.

3. Using Spring Test

Spring 테스트 모듈에는 MockRestServiceServer라는 모의 서버가 포함되어 있습니다. 이 접근 방식을 사용하면 RestTemplate 인스턴스를 통해 특정 요청이 전달될 때 특정 객체를 반환하도록 서버를 구성합니다. 또한 모든 기대 사항이 충족되었는지 여부를 해당 서버 인스턴스에서 verify()할 수 있습니다.

MockRestServiceServer는 실제로 MockClientHttpRequestFactory를 사용하여 HTTP API 호출을 가로채는 방식으로 작동합니다. 구성에 따라 예상 요청 및 해당 응답 목록을 생성합니다. RestTemplate 인스턴스가 API를 호출하면 예상 목록에서 요청을 조회하고 해당 응답을 반환합니다.

따라서 모의 응답을 보내기 위해 다른 포트에서 HTTP 서버를 실행할 필요가 없습니다.

MockRestServiceServer를 사용하여 동일한 getEmployee() 예제에 대한 간단한 테스트를 만들어 보겠습니다.

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = SpringTestConfig.class)
public class EmployeeServiceMockRestServiceServerUnitTest {

    @Autowired
    private EmployeeService empService;
    @Autowired
    private RestTemplate restTemplate;

    private MockRestServiceServer mockServer;
    private ObjectMapper mapper = new ObjectMapper();

    @BeforeEach
    public void init() {
        mockServer = MockRestServiceServer.createServer(restTemplate);
    }
    
    @Test                                                                                          
    public void givenMockingIsDoneByMockRestServiceServer_whenGetIsCalled_thenReturnsMockedObject()() {   
        Employee emp = new Employee("E001", "Eric Simmons");
        mockServer.expect(ExpectedCount.once(), 
          requestTo(new URI("http://localhost:8080/employee/E001")))
          .andExpect(method(HttpMethod.GET))
          .andRespond(withStatus(HttpStatus.OK)
          .contentType(MediaType.APPLICATION_JSON)
          .body(mapper.writeValueAsString(emp))
        );                                   
                       
        Employee employee = empService.getEmployee(id);
        mockServer.verify();
        Assertions.assertEquals(emp, employee);                                                        
    }
}

이전 코드 조각에서는 MockRestRequestMatchersMockRestResponseCreators의 정적 메서드를 사용하여 REST 호출에 대한 기대와 응답을 명확하고 읽기 쉬운 방식으로 정의했습니다.

import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;      
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;

테스트 클래스의 RestTemplateEmployeeService 클래스에서 사용된 인스턴스와 동일해야 한다는 점을 명심해야 합니다. 이를 보장하기 위해 Spring 구성에서 RestTemplate 빈을 정의하고 테스트와 구현 모두에서 인스턴스를 자동 연결했습니다.

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

MockRestServiceServer를 사용하는 것은 통합 테스트를 작성할 때 매우 유용하며 외부 HTTP 호출만 모의해야 합니다.

0개의 댓글