Às vezes, nos aplicativos, é útil ter um console para gerenciar o aplicativo diretamente do servidor. Uma das soluções extremamente convenientes para esse problema é o Spring Shell.
Os testes também são uma prática muito boa (espero que você os tenha) e, às vezes, são gravados com a anotação @SpringBootTest. No entanto, se você conectar o Spring Shell e tentar executar esse teste, ... seu teste simplesmente congelará em antecipação a um comando do console.
Então, nós estamos indo em busca de uma solução.Google
Após uma breve pesquisa no GitHub, encontramos um problema semelhante .
Para testar o shell, o autor sugere substituir o compartimento pelo tipo ApplicationRunner, que espera um comando do console. Aqui está a solução para acessar e testar os próprios comandos definidos em @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);
}
}
Infelizmente, os testes com esta solução ainda estão pendentes aguardando a equipe.É hora de olhar para baixo do capô!
Após uma depuração leve, encontramos o seguinte código na classe 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);
}
}
}
Em outras palavras, o Spring Boot simplesmente adiciona nossa lixeira com ApplicationRunner personalizado às já definidas e lança todas elas.Parece que a solução é simples - redefina a lixeira! Hora de entrar na fonte do Spring Shell.
Redefinir feijão
Torna-se rapidamente claro que a classe JLineShellAutoConfiguration é responsável por criar os corredores, especificamente estamos interessados no bean scriptApplicationRunner, que impede o início do teste.
, ( 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;
Uau, tudo parece claro agora - volte para application.properties e escreva:
spring.shell.script.spring.shell.script=false
Cruze seus dedos. Execute o teste. Trabalho.
O caso está resolvido, obrigado por sua atenção.