복붙노트

[SPRING] Spring JUnit : autowired 컴포넌트에서 autowired 컴포넌트를 모의하는 법

SPRING

Spring JUnit : autowired 컴포넌트에서 autowired 컴포넌트를 모의하는 법

테스트하고 싶은 Spring 구성 요소가 있고이 구성 요소는 단위 테스트의 목적으로 변경해야하는 autowired 특성을 가지고 있습니다. 문제는 클래스가 post-construct 메서드 내에서 autowired 구성 요소를 사용하므로 실제로 사용되기 전에이를 (예 : ReflectionTestUtils를 통해) 대체 할 수 없다는 것입니다.

어떻게해야합니까?

이것은 테스트하고 싶은 클래스입니다.

@Component
public final class TestedClass{

    @Autowired
    private Resource resource;

    @PostConstruct
    private void init(){
        //I need this to return different result
        resource.getSomething();
    }
}

그리고 이것은 테스트 케이스의 기본입니다 :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= "classpath:applicationContext.xml")
public class TestedClassTest{

    @Autowired
    private TestedClass instance;

    @Before
    private void setUp(){
        //this doesn't work because it's executed after the bean is instantiated
        ReflectionTestUtils.setField(instance, "resource", new Resource("something"));
    }
}

postconstruct 메서드가 호출되기 전에 리소스를 다른 것으로 바꾸는 방법이 있습니까? Spring JUnit 러너에게 다른 인스턴스를 autowire하도록 말하고 싶습니까?

해결법

  1. ==============================

    1.정의한 @Autowired bean이 테스트에 필요한 유형의 새 testContext.xml을 제공 할 수 있습니다.

    정의한 @Autowired bean이 테스트에 필요한 유형의 새 testContext.xml을 제공 할 수 있습니다.

  2. ==============================

    2.당신은 모키토를 사용할 수 있습니다. 특히 PostConstruct에서는 확실하지 않지만 일반적으로 다음과 같이 작동합니다.

    당신은 모키토를 사용할 수 있습니다. 특히 PostConstruct에서는 확실하지 않지만 일반적으로 다음과 같이 작동합니다.

    // Create a mock of Resource to change its behaviour for testing
    @Mock
    private Resource resource;
    
    // Testing instance, mocked `resource` should be injected here 
    @InjectMocks
    @Resource
    private TestedClass testedClass;
    
    @Before
    public void setUp() throws Exception {
        // Initialize mocks created above
        MockitoAnnotations.initMocks(this);
        // Change behaviour of `resource`
        when(resource.getSomething()).thenReturn("Foo");   
    }
    
  3. ==============================

    3.Spring Boot 1.4는 @MockBean이라는 테스트 주석을 도입했습니다. 그래서 Spring Bean을 조롱하고 감시하는 것은 Spring Boot에 의해 기본적으로 지원됩니다.

    Spring Boot 1.4는 @MockBean이라는 테스트 주석을 도입했습니다. 그래서 Spring Bean을 조롱하고 감시하는 것은 Spring Boot에 의해 기본적으로 지원됩니다.

  4. ==============================

    4.Spring-reinject https://github.com/sgri/spring-reinject/가있는 mock으로 bean 정의를 오버라이드 할 수 있습니다.

    Spring-reinject https://github.com/sgri/spring-reinject/가있는 mock으로 bean 정의를 오버라이드 할 수 있습니다.

  5. ==============================

    5.주제에 대한 블로그 게시물을 만들었습니다. 또한 작업 예제와 함께 Github 저장소에 대한 링크를 포함합니다.

    주제에 대한 블로그 게시물을 만들었습니다. 또한 작업 예제와 함께 Github 저장소에 대한 링크를 포함합니다.

    그 트릭은 원래의 스프링 빈을 흉내로 덮어 쓰는 테스트 설정을 사용하고있다. @Primary 및 @Profile 주석을이 트릭에 사용할 수 있습니다.

  6. ==============================

    6.통합 테스트의 또 다른 접근법은 새 Configuration 클래스를 정의하고이를 @ContextConfiguration으로 제공하는 것입니다. 환경 설정에서 bean을 조롱 할 수있을뿐만 아니라 test / s flow에서 사용하고있는 모든 bean 유형을 정의해야합니다. 예를 들면 다음과 같습니다.

    통합 테스트의 또 다른 접근법은 새 Configuration 클래스를 정의하고이를 @ContextConfiguration으로 제공하는 것입니다. 환경 설정에서 bean을 조롱 할 수있을뿐만 아니라 test / s flow에서 사용하고있는 모든 bean 유형을 정의해야합니다. 예를 들면 다음과 같습니다.

    @RunWith(SpringRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class)
    public class MockTest{
     @Configuration
     static class ContextConfiguration{
     // ... you beans here used in test flow
     @Bean
        public MockMvc mockMvc() {
            return MockMvcBuilders.standaloneSetup(/*you can declare your controller beans defines on top*/)
                    .addFilters(/*optionally filters*/).build();
        }
     //Defined a mocked bean
     @Bean
        public MyService myMockedService() {
            return Mockito.mock(MyService.class);
        }
     }
    
     @Autowired
     private MockMvc mockMvc;
    
     @Autowired
     MyService myMockedService;
    
     @Before
     public void setup(){
      //mock your methods from MyService bean 
      when(myMockedService.myMethod(/*params*/)).thenReturn(/*my answer*/);
     }
    
     @Test
     public void test(){
      //test your controller which trigger the method from MyService
      MvcResult result = mockMvc.perform(get(CONTROLLER_URL)).andReturn();
      // do your asserts to verify
     }
    }
    
  7. from https://stackoverflow.com/questions/19299513/spring-junit-how-to-mock-autowired-component-in-autowired-component by cc-by-sa and MIT license