如何在@SpringBootTest中传递程序参数?

时间:2017-02-21 20:25:26

标签: java spring spring-boot

我正在构建一个spring boot应用程序。我想像这样运行它:

 java -jar myjar.jar inputFile outputFile

如何为此编写@SpringBootTest?我想使用@SpringBootTest会使Spring在启动时失败,因为我的一些代码会说,"你需要提供一个inputFile和outputFile"。有没有办法在使用@SpringBootTest时传递程序参数?

I'm inferring from this answer我可能必须使用SpringApplicationBuilder来执行此操作。

思考我有答案,但我错了。这些不正确的信息可能对某些人有用:

这个信息是错误的。我认为某些参数在代码中不能作为属性引用,但不是全部。我仍然不知道如何在一个参数中获取应用程序参数@SpringBootTest )我很困惑,因为我不理解术语。注释具有"属性"的参数。我以为是将它指向属性文件but the documentation says

  

表单中的属性key =应在测试运行之前添加到Spring Environment的值。

术语难题的另一部分是我所谓的"程序参数" Spring文档称为"属性"。

这是一些其他相关文档:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-application-arguments

这是一种解决方法(不是答案)。你可以这样做:

private SpringApplicationBuilder subject;

@Before
public void setUp() throws Exception {
    subject = new SpringApplicationBuilder(Application.class);
}

@Test
public void requiresInputAndOutput() throws Exception {

    thrown.expect(IllegalStateException.class);
    subject.run();
}

@Test
public void happyPathHasNoErrors() throws Exception {

    subject.run(EXISTING_INPUT_FILE, "does_not_exist");
}

我不太喜欢这个。它阻止我在测试中的其他地方使用@Autowired

4 个答案:

答案 0 :(得分:1)

我有同样的问题。 SpringBootContextLoader(默认情况下与@SpringBootTest一起使用)always runs your app without any arguments。但是,您可以提供自己的引导程序,然后引导程序可以提供您自己的SpringApplication,该调用会被调用以运行测试。从那里,您可以覆盖run(String... args)方法以提供所需的任何参数。

例如,给出一个简单的应用程序:

@SpringBootApplication
public class Main {
    public static void main(final String[] args) {
        new SpringApplicationBuilder(Main.class).run(args);
    }

    @Bean
    public ApplicationRunner app() {
        return args -> System.out.println(args.getOptionNames());
    }
}

您可以使用以下命令注入测试参数:

@ContextConfiguration(classes = Main.class)
@ExtendWith(SpringExtension.class)
@BootstrapWith(RestartAppsTest.Bootstrapper.class)
class RestartAppsTest {

    static class Bootstrapper extends SpringBootTestContextBootstrapper {
        static class ArgumentSupplyingContextLoader extends SpringBootContextLoader {
            @Override
            protected SpringApplication getSpringApplication() {
                return new SpringApplication() {
                    @Override
                    public ConfigurableApplicationContext run(String... args) {
                        return super.run("--restart");
                    }
                };
            }
        }

        @Override
        protected Class<? extends ContextLoader> getDefaultContextLoaderClass(Class<?> testClass) {
            return ArgumentSupplyingContextLoader.class;
        }
    }

    @Test
    void testRestart() {
        // 
    }
}

它显然有点冗长,但可以。您可以清理它并制作一个更好/可重用的引导程序,以查找您自己的注释(或可能重用JUnit Jupiter的@Arguments),该注释声明要提供的参数(而不是对其进行硬编码)。

答案 1 :(得分:0)

通常,您正在为您的服务编写测试;不是引导过滤器。 Spring Boot会将命令行参数传递给您的类 - 可能使用@Value注释,而@Value注释又是您服务的参数。考虑使用SpringRunner测试您的服务。这是我的代码库中的一个示例。

SELECT sum1, sum2
FROM (subquery1 here) as table1 
JOIN (subquery2 here) as table2
ON (join condition); 

答案 2 :(得分:0)

如果您应用的主要方法看起来有点不同,则可以使用@SpringBootTest(classes=Application.class, args ={inputFile, outputFile})

public static void main(String[] args){ 
     SpringApplication.run(Application.class, args);
}

答案 3 :(得分:0)

对我来说工作示例是

@SpringBootTest(args ={"--env", "test"})
class QuickFixServerAppTest {

    @Test
    void loadContextTest() {
    }
}

与传递相同

--env test

启动Spring时的参数