Menulis tes @SpringBootTest saat menggunakan Spring Shell dalam suatu aplikasi

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 {
		//do nothing
	}
	

}

@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";

	/**
	 * The name of the environment property that allows to disable the behavior of this
	 * runner.
	 */
	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.


All Articles