
이슈 선정
https://github.com/spring-projects/spring-boot/issues/46853
Allow user-override of beans created in MockRestServiceServerAutoConfiguration · Issue #46853 · spring-projects/spring-boot
Description There is a design flaw in customizing the @RestClientTest auto-configuration MockRestServiceServerAutoConfiguration. You cannot add your own RestClientCustomizer bean when using @RestCl...
github.com
이슈의 내용은 Spring 테스트 슬라이스인 @RestClientTest 어노테이션을 사용할때 MockRestServiceServer를 주입해서 사용하면
사용자가 주입한 RestClientCustomizer가 적용되지 않는다. MockRestServiceServerAutoConfiguration의 커스터마이저가 순서, 백오프 문제로 사용자 설정을 덮어씌워 버리는 문제라는것이다.
@RestClientTest (테스트 환경)
웹 클라이언트만을 테스트 하기 위해 나머지 db,컨트롤러등 빈을 띄우지 않는 테스트 어노테이션이다.
스프링은 테스트를 위해 RestClient만을 위해 빈을 로딩한다. 이때 자동적으로 MockRestServiceServer도 구성해준다
RestClient (테스트 대상)
실제로 외부 API를 호출하는 HTTP 클라이언트 객체이다.
사용자는 이슈에서 응답 본문을 두번 읽고싶기에 버퍼링 기능을 키고싶어했다.
MockRestServiceServer (가짜서버)
RestClient가 요청을 보낼때 중간에서 가로채서 가짜 응답을 준다.
RestClient에게 가짜서버랑 통신해야 한다고 알려줘야 한다.
MockRestServiceServerAutoConfiguration
@RestClient가 선언되면 자동으로 실행되어 MockRestServiceServer를 빈으로 등록하고 자동으로 설정을 마치는 자동 설정 클래스이다.
즉 정리하면
사용자의 의도:
"나는 RestClient가 응답을 두 번 읽을 수 있게(Buffering) 설정하고 싶어. 내가 직접 Customizer 빈을 만들어서 bufferContent = true로 설정해야지!"
스프링 부트의 버그:
"어? @RestClientTest네? 내가 도와줄게! RestClient랑 MockServer랑 연결하려면 Customizer가 필요해. 내 마음대로 기본 설정(bufferContent = false)이 된 Customizer를 하나 더 만들어서 등록해야지!"
와 같은 상황이 되어 원하는 결과를 얻을수 없게 된다.
해결 방법
간단하게 @ConditionalOnMissingBean(MockServerRestClientCustomizer.class) 하나만 붙이면된다.
@Bean
@ConditionalOnMissingBean(MockServerRestClientCustomizer.class)
MockServerRestClientCustomizer mockServerRestClientCustomizer() {
return new MockServerRestClientCustomizer();
}
하지만 이 어노테이션을 붙인다고 제대로 돌아간다는 보장이 없기에 테스트를 세세하게 작성했다.
class MockRestServiceServerAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MockRestServiceServerAutoConfiguration.class));
@Test
void registersRestClientCustomizerWhenMissing() {
this.contextRunner
.withPropertyValues("spring.test.restclient.mockrestserviceserver.enabled=true")
.run((context) -> assertThat(context).hasSingleBean(MockServerRestClientCustomizer.class));
}
@Test
void backsOffWhenUserProvidesRestClientCustomizer() {
this.contextRunner
.withPropertyValues("spring.test.restclient.mockrestserviceserver.enabled=true")
.withUserConfiguration(UserConfig.class)
.run((context) -> {
assertThat(context).hasSingleBean(MockServerRestClientCustomizer.class);
assertThat(context.getBean(MockServerRestClientCustomizer.class))
.isSameAs(context.getBean("userMockServerRestClientCustomizer"));
});
}
@Configuration(proxyBeanMethods = false)
static class UserConfig {
@Bean(name = "userMockServerRestClientCustomizer")
MockServerRestClientCustomizer userMockServerRestClientCustomizer() {
return new MockServerRestClientCustomizer();
}
}
}
먼저 컨테이너의 빈등록 여부를 확인하기 위해 스프링 컨테이너를 생성해주는 ApplicationContextRunner 객체를 생성하고 그 안에MockRestServiceServerAutoConfiguration.class 빈을 넣어주었다. 이렇게 하면 내가 검증하고 싶은 Config 클래스만 빈 등록 시도가 가능하다.
그다음 회귀테스트인 registersRestClientCustomizerWhenMissing를 작성해주었다. 사용자가 따로 빈 등록을 안했기 떄문에 무조건 빈이 하나인지(hasSingleBean) 검사해준다.
마지막으로 UserConfig라는 유저용 빈을 만들어 등록을 해주고 유저가 Customizer를 사용할때 유저의 빈이 등록되었다면 테스트가 성공하고 기본 설정 빈이 사용될경우 테스트가 실패하도록 만들어 주었다.

1월 16일자로 머지가 되었다!!
메인테이너의 리뷰로 빈 등록을 문제의 객체 뿐만 아니라 같은 클래스에 있는 나머지 객체도 해주어야 한다는 요청을 받았고 나머지 빈들도 추가해주었지만 그에 대한 테스트는 내가 깜빡하고 추가하지 않아서 메인테이너가 테스트를 추가해준듯 하다.

느낀 점
그동안 테스트는 단위테세트, 즉 비즈니스 로직을 검증하는 테스트가 전부라고 느꼈다.
하지만 이번 기여를 통하여 빈의 이름을 검증할 수 도 있다는걸 알았다.
앞으로 개발을 하면서 비즈니스로직 뿐만 아니라 여러 테스트를 진행해야 할 때가 있을텐데, 오늘의 가르침을 써먹어야 겠다.
'오픈소스 기여일지' 카테고리의 다른 글
| [Spring-boot] 빌드팩 설정에서 CLI 환경 환경변수 추가 기능 구현 (2) | 2026.01.13 |
|---|