كتابة اختباراتSpringBootTest عند استخدام Spring Shell في تطبيق

في بعض الأحيان في التطبيقات ، من المفيد أن يكون لديك وحدة تحكم لإدارة التطبيق مباشرة من الخادم. واحدة من الحلول المريحة للغاية لهذه المشكلة هي Spring Shell.


تعتبر الاختبارات أيضًا ممارسة جيدة جدًا (آمل أن تكون لديك) ، وأحيانًا تتم كتابتها باستخدام التعليق التوضيحيSpringBootTest. ومع ذلك ، إذا قمت بتوصيل Spring Shell وحاولت تشغيل مثل هذا الاختبار ، فعندئذٍ ... سوف يتجمد اختبارك تحسبًا لأمر من وحدة التحكم.


لذلك ، نحن نبحث عن حل.

جوجل


بعد بحث قصير على GitHub ، وجدنا مشكلة مشابهة .


لاختبار الغلاف ، يقترح المؤلف تجاوز الحاوية بنوع ApplicationRunner ، الذي يتوقع أوامر من وحدة التحكم. فيما يلي حل الوصول إلى الأوامر نفسها واختبارها المحددة في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);
		
		
	}
	
	
}

للأسف ، لا تزال الاختبارات مع هذا الحل معلقة في انتظار الفريق.

حان الوقت للنظر تحت غطاء محرك السيارة!


بعد تصحيح الأخطاء ، نجد الكود التالي في فئة 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 المخصص إلى تلك المحددة مسبقًا ويطلقها جميعًا.

يبدو أن الحل بسيط - إعادة تعريف الحاوية! حان الوقت للوصول إلى مصدر Spring Shell.


أعد تعريف الفول


يصبح من الواضح بسرعة أن فئة JLineShellAutoConfiguration هي المسؤولة عن إنشاء العدائين ، على وجه التحديد نحن مهتمون بالبرنامج النصي ApplicationRunner 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";

	/**
	 * 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;

واو ، يبدو كل شيء واضحًا الآن - ارجع إلى application.properties واكتب:


spring.shell.script.spring.shell.script=false 

لنأمل ذلك. قم بإجراء الاختبار. يعمل.


تم حل القضية ، شكرا لكم على اهتمامكم.


All Articles