有时在应用程序中,拥有一个控制台可以直接从服务器管理应用程序很有用。Spring Shell是解决此问题的极为方便的解决方案之一。
测试也是一种很好的做法(我希望您拥有它们),有时,它们是使用@SpringBootTest批注编写的。但是,如果您插入Spring Shell并尝试运行这样的测试,则...您的测试将仅冻结在预期来自控制台的命令中。
因此,我们正在寻找解决方案。谷歌
在GitHub上进行简短搜索后,我们发现了类似的问题。
为了测试外壳,作者建议使用ApplicationRunner类型覆盖bin,这需要控制台提供命令。这是用于访问和测试@ShellComponent中定义的命令本身的解决方案。
@Component
public class CliAppRunner implements ApplicationRunner {
public CliAppRunner() {
}
@Override
public void run(ApplicationArguments args) throws Exception {
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes =CliConfig.class)
public class ShellCommandIntegrationTest {
@Autowired
private Shell shell;
@Test
public void runTest(){
Object result=shell.evaluate(new Input(){
@Override
public String rawText() {
return "add 1 3";
}
});
DefaultResultHandler resulthandler=new DefaultResultHandler();
resulthandler.handleResult(result);
}
}
不幸的是,使用此解决方案的测试仍在等待团队进行。现在是时候仔细看了!
经过轻调试之后,我们在SpringApplication类中找到以下代码:
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
换句话说,Spring Boot只需将带有自定义ApplicationRunner的bin添加到已经定义的bin中,然后启动它们。看来解决方案很简单-重新定义垃圾箱!是时候了解Spring Shell的源代码了。
重新定义豆
很明显,JLineShellAutoConfiguration类负责创建运行器,特别是我们对scriptApplicationRunner bean感兴趣,它阻止了测试的开始。
, ( spring.main.allow-bean-definition-overriding=true Spring 2.+):
@TestConfiguration
static class Runner {
@Bean
public ApplicationRunner scriptApplicationRunner(){
return new CliAppRunner();
}
}
, . JLineShellAutoConfiguration Runner scriptApplicationRunner. ( — - — , ?).
, , JLineShellAutoConfiguration:
@Bean
@ConditionalOnProperty(prefix = SPRING_SHELL_SCRIPT, value = ScriptShellApplicationRunner.ENABLED, havingValue = "true", matchIfMissing = true)
public ApplicationRunner scriptApplicationRunner(Parser parser, ConfigurableEnvironment environment) {
return new ScriptShellApplicationRunner(parser, shell, environment);
}
, — property, . application.properties:
spring.shell.script.enabled=false
. . .
ScriptShellApplicationRunner , property. :
public static final String SPRING_SHELL_SCRIPT = "spring.shell.script";
public static final String ENABLED = "spring.shell.script";
public static final String SPRING_SHELL_SCRIPT_ENABLED = SPRING_SHELL_SCRIPT + "." + ENABLED;
哇,现在一切似乎都很清楚-返回application.properties并编写:
spring.shell.script.spring.shell.script=false
交叉手指。运行测试。作品。
该案已解决,谢谢您的关注。