在应用程序中使用Spring Shell时编写@SpringBootTest测试

有时在应用程序中,拥有一个控制台可以直接从服务器管理应用程序很有用。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 {
		//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的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";

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