我想为此私有方法创建一个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实现模拟对象的正确方法是什么?
答案 0 :(得分:1)
关于为什么不应该/避免为私有方法编写单元测试的争论/见解很多。看看这个SO问题,它可以帮助您做出决定并提供更多见解-How do I test a private function or a class that has private methods, fields or inner classes?
但是,如果您想实现已发布的内容,则可以;让我细分一下未能通过测试的事情。
Spring Boot测试需要使用@SpringBootTest
注释(如果使用JUnit 5),并且如果使用JUnit 4,则需要注释@RunWith(SpringRunner.class)
。
您不应该在测试中使用new
运算符来创建类的实例,而让Test上下文使用@Autowired
或任何其他类似的机制来自动加载类
要模拟输入参数并调用私有方法,可以使用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);
}
}