Terkadang dalam aplikasi, ada baiknya memiliki konsol untuk mengelola aplikasi secara langsung dari server. Salah satu solusi yang sangat nyaman untuk masalah ini adalah Spring Shell.
Tes juga merupakan praktik yang sangat baik (saya harap Anda memilikinya) dan, kadang-kadang, tes ini ditulis dengan anotasi @SpringBootTest. Namun, jika Anda mencolokkan Spring Shell dan mencoba menjalankan pengujian seperti itu, maka ... pengujian Anda akan membeku untuk mengantisipasi perintah dari konsol.
Jadi, kami akan mencari solusi.Google
Setelah pencarian singkat di GitHub, kami menemukan masalah serupa .
Untuk menguji shell, penulis menyarankan menimpa nampan dengan tipe ApplicationRunner, yang mengharapkan perintah dari konsol. Berikut adalah solusi untuk mengakses dan menguji sendiri perintah yang didefinisikan dalam @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);
}
}
Sayangnya, tes dengan solusi ini masih menunggu untuk tim.Sudah waktunya untuk melihat di bawah tenda!
Setelah debug ringan, kami menemukan kode berikut di kelas 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);
}
}
}
Dengan kata lain, Spring Boot hanya menambahkan nampan kami dengan ApplicationRunner khusus ke yang sudah ditentukan dan meluncurkan semuanya.Tampaknya solusinya sederhana - mendefinisikan kembali tempat sampah! Saatnya masuk ke sumber Spring Shell.
Mendefinisikan ulang kacang
Dengan cepat menjadi jelas bahwa kelas JLineShellAutoConfiguration bertanggung jawab untuk membuat pelari, khususnya kami tertarik pada kacang scriptApplicationRunner, yang mencegah pengujian kami dari mulai.
, ( 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;
Wow, semuanya tampak jelas sekarang - kembali ke application.properties dan tulis:
spring.shell.script.spring.shell.script=false
Silangkan jarimu. Jalankan tes. Bekerja
Kasus ini terpecahkan, terima kasih atas perhatian Anda.