使用ContextRefreshedEvent参数为私有方法创建JUnit

时间:2019-10-15 22:18:35

标签: java spring spring-boot junit

我想为此私有方法创建一个JUnit测试:

@Component
public class ReportingProcessor {

    @EventListener
    private void collectEnvironmentData(ContextRefreshedEvent event) {
    }
}

我尝试过:

@SpringBootApplication
public class ReportingTest {

    @Bean
    ServletWebServerFactory servletWebServerFactory() {
        return new TomcatServletWebServerFactory();
    }

    @Test
    public void reportingTest() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {


        GenericApplicationContext parent = new GenericApplicationContext();
        parent.refresh();
        ConfigurableApplicationContext context = new SpringApplicationBuilder(Configuration.class).parent(parent).run();
        ContextRefreshedEvent refreshEvent = new ContextRefreshedEvent(context);        

        ReportingProcessor instance = new ReportingProcessor();

        Method m = ReportingProcessor.class.getDeclaredMethod("collectEnvironmentData", ContextRefreshedEvent.class);
        m.setAccessible(true);
        m.invoke(instance, refreshEvent);               
    }
}

但是我得到了例外:Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.

为ContextRefreshedEvent实现模拟对象的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

关于为什么不应该/避免为私有方法编写单元测试的争论/见解很多。看看这个SO问题,它可以帮助您做出决定并提供更多见解-How do I test a private function or a class that has private methods, fields or inner classes?

但是,如果您想实现已发布的内容,则可以;让我细分一下未能通过测试的事情。

  1. Spring Boot测试需要使用@SpringBootTest注释(如果使用JUnit 5),并且如果使用JUnit 4,则需要注释@RunWith(SpringRunner.class)

  2. 您不应该在测试中使用new运算符来创建类的实例,而让Test上下文使用@Autowired或任何其他类似的机制来自动加载类

  3. 要模拟输入参数并调用私有方法,可以使用Powermockito库。请注意,如果您的场景不需要调用私有方法,那么mockito库对于几乎所有模拟场景都足够了。

下面是应该起作用的测试:

@SpringBootTest
public class ReportingProcessorTest {

    @Autowired
    ReportingProcessor reportingProcessor;

    @Test
    public void reportingTest() throws Exception {

        ContextRefreshedEvent contextRefreshedEvent = PowerMockito.mock(ContextRefreshedEvent.class);
        Whitebox.invokeMethod(reportingProcessor, "collectEnvironmentData", contextRefreshedEvent);

    }
}