관리 메뉴

제뉴어리의 모든것

SpringBoot Test에서 현재 등록된 빈 조회하기 (어떤 환경에서든지 가능) 본문

Spring Boot

SpringBoot Test에서 현재 등록된 빈 조회하기 (어떤 환경에서든지 가능)

제뉴어리맨 2022. 9. 13. 01:03
  • ApplicationContextProvider
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component //빈으로 등록
public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext ctx = null;

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }

    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.ctx = ctx;
    }
}

 

  • BeanUtils
import org.springframework.context.ApplicationContext;

public class BeanUtils {

    static ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();

    public static Object getBean(String beanId) {

        if( applicationContext == null ) {
            throw new NullPointerException("Spring의 ApplicationContext초기화 안됨");
        }

        return applicationContext.getBean(beanId);
    }

    public static String[] getDefinitionNames() {

        return applicationContext.getBeanDefinitionNames();
    }
}

 

  • @SpringBootTest 를 사용한 Junit을 이용한 Test환경에서 현재 등록된 빈 조회 코드
@SpringBootTest
@AutoConfigureMockMvc
public class MemberControllerMockTest {

    @Test
    void beanFind() throws Exception {

        String[] definitionNames = BeanUtils.getDefinitionNames();
        for (String definitionName : definitionNames) {
            Object bean = BeanUtils.getBean(definitionName);
            System.out.println(bean);
        }
    }
}

 

 

 

위에 기능이 필요했던 이유는

@MockBean 애노테이션과 @Autowired 애노테이션을 이용하여 빈을 주입 받았을때,

어떤 차이가 있는지 확인하고 싶었기 때문이다.

그리고 @MockBean 애노테이션에 대해 알아보면서

어떤 블로그에서는 @MockBean을 붙이면 해당 필드의 객체가 스프링 컨테이너에 추가로 등록된다는 글과

또 다른 블로그에서는 앱에서 @Component가 붙어 기존에 등록될 객체를 Mock으로 대체해서 빈으로 등록해준다는 글이 있어서 둘중에 어떤 것이 맞는지 확인하기 위해서이다.

예를들어, MemberService라는 클래스가 앱에서 @Component 애노테이션으로 인해 빈으로 등록되는데

Test에서 

MemberService를 @MockBean 으로 의존성 주입받을때,

실제 MemberService 빈, 가짜 MemberService 빈 이렇게 두개가 등록될지

실제 MemberService 빈을 대체하여 가짜 MemberService가 등록될지가 궁금했던것이다. 

 

테스트에 필요한 클래스는 위에 적은 ApplicationContextProvider, BeanUtils 와

아래에 적은 MockBeanTest 클래스 이다.

 

 

  • Test에 만들어진 클래스 항목 (MemberControllerMockTest 제외한 빨간박스 안에 세개의 클래스이다)

  • 테스트 코드
import com.codestates.member.service.MemberService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

@SpringBootTest
public class MockBeanTest {

    @MockBean
//    @Autowired
    private MemberService memberService;

    @Test
    void mockBeanAndAutowiredAnnotationTest() {
        /**
         * 빈 전체 조회
         */
//        String[] definitionNames = BeanUtils.getDefinitionNames();
//        for (String definitionName : definitionNames) {
//            Object bean = BeanUtils.getBean(definitionName);
//            System.out.println(bean);
//        }

        String[] definitionNames = BeanUtils.getDefinitionNames();
        for (String definitionName : definitionNames) {
            Object bean = BeanUtils.getBean(definitionName);

            if(bean.getClass().getName().contains("MemberService"))
                System.out.println(bean);
        }
    }
}

 

  • 결과 화면

보시다시피

memberService로 등록된 빈은 하나이다.

즉, 

@MockBean을 붙여서 필드를 생성하면

해당 클래스의 진짜빈, 가짜빈 두개가 등록되는것이 아니라,

진짜빈을 대체하여 가짜빈 하나만 등록된다.

 

정말 확식하게 확인하고 싶다면 위에 주석처리한 코드로 전체 빈을 조회해보면 된다.

 

역시 모든 블로그를 다 믿을 수 없다.

블로그 내용을 가려서 보자.

 

 

참조 : https://bluexmas.tistory.com/497