Spring i.o 에서 Spring Boot 3.4.4 버전을 사용해 테스트 해 보았다

 

✅ @MockBean deprecated → @MockitoBean 으로 대체

@SpyBean 도 마찬가지 → @MockitoSpyBean 으로 대체

 

✅ @MockBean 은 무엇이었나?

Spring boot 에서 제공하는 가짜 Bean 객체.

특히 통합 테스트 이상의 테스트를 할 경우, application context 를 구성하는 특정 컴포넌트들을 mocking 하는게 필요한 경우들이 존재함.

 

✅ WHY deprecated?

Spring Boot 에서 @MockBean 제거 → bean 대체자 지원을 Spring framework 단 에서 제공할 수 있도록함 : @MockitoBean

이로서 Spring Boot 프로젝트가 아닌 Spring 프로젝트에서도 이를 사용가능함.

스프링 프로젝트 팀 관점에서 좀 더 적절한 모듈 로 이를 이동시킨 것으로 보인다 

 

 

 

✅ 완전히 동일한가?

  • 회사의 test coverage 를 채우기 위해 작성되어 있는 코드들을 구경하면 @MockBean 이 굉장히 많이 사용되고 있길래, 과연 이 코드들이 spring boot 3.4 로 업그레이드 하여도 안전할지.. @MockitoBean 이 compatibility 를 제공하는지 찾아보았다.
  • 찾아보니 완전히 동일하다고 볼 수는 없을 것 같다. incompatability 가 발생하고 있다. 이에 따라 사용자들의 상당한 반발이 있고 스프링 팀에서는 release note 에 deprecation 과 새로운 어노테이션 도입에 따른 차이를 명시하기 시작함. → https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes#deprecation-of-mockbean-and-spybean
  • 예를들어 @MockitoBean 은 @MockBean 처럼 @Component 클래스 내의 필드로 주입되지가 않는 상황들이 발생하고 있다고 함. → 특히 이것 때문에 @TestConfiguration class 에 Mock bean 객체를 필드 주입하는 것도 불가한 상황.

 

기존에는 아래와 같은 사용이 가능했다면 현재는 불가한 것

@TestConfiguration
public class MyTestConfiguration {
	@MockBean
    private PublishCouponService publishCouponService; // 이게 불가능함 
    ...
    
@Import(MyTestConfiguration.class) // 주로 이런식으로 썼었는데 ㅠㅠ 
public class CouponController {
	@Autowired
    private CouponController couponController;

 

 

Spring boot 3.4 부터는

@TestConfiguration class 에 mockBean 을 필드주입하는 방식으로는 사용할수가 없는 상황이다

 

따라서 아래와 같은 방식으로 사용해야 하는 것으로 보인다 

@WebMvcTest(controllers = {CouponController.class})
@MockitoBean(types = {PublishCouponService.class}) // 여기에 적어주거나
public class CouponControllerTest {
	@Autowired
    private CouponController couponController;
		...

 

또는

@WebMvcTest(controllers = {CouponController.class})
public class CouponControllerTest {
	@Autowired
    private CouponController couponController;
		
	@MockitoBean
	private PublishCouponService publishCouponService; // 요렇게 하거나

와 같이 Test class  자체에 필드 주입은 가능하나

@TestConfiguration class 에 mockBean 을 필드주입하는 방식으로는 사용할수 없음.

Test class 에 대한 필드 주입은 가능하니 공통의 BaseTestClass 같은거를 두고 상속하는 방식은 여전히 가능함.

하지만 Java 에서의 상속은 1번만 가능하고, 조합의 개념은 아니라는 것 때문에 개인적으로는 Import 를 쓰는 거를 좋아했었음.

 

 

 

@TestConfiguration 에 목빈을 주입해두는 걸 정 하고 싶다면

좋은 모습인지는 모르겠지만 아래와 같이도 할 수 있다

@TestConfiguration
public class MyTestConfiguration {
	// 걍 테스트용 Mock Bean 을 직접 만들거나 ㅎ
    @Bean
    PublishCouponService publishCouponService() {
        return Mockito.mock(PublishCouponService.class);
    }
}

 

 

 

사람들이 엄청 싸우고 있다

 

많은 사람들이 @TestConfiguration 내에 @MockBean 을 필드 주입하여 사용하며 이를 각종 테스트에서 재사용 할 수 있도록 하는 구조를 취하고 있었나봄.

 

나도 Base Class 를 단순 상속하는 것보다 Testconfiguration 을 Import 해가며 쓰고 있었는데 고민된다. 

 

어떻게 해야 Application Context 를 덜 로딩하면서, 테스트 클래스들 간에 확장 가능한 구조로 만들 수 있을까?

하나의 공통 상위 클래스를 잘 설계하는 걸 고민해야할까?🤔

 

 

MockitoBean (Spring Framework 6.2.4 API)

Name of the bean to mock. If left unspecified, the bean to mock is selected according to the configured types or the annotated field's type, taking qualifiers into account if necessary. See the class-level documentation for details.

docs.spring.io

 

 

복사했습니다!