繁体   English   中英

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

[英]How do you pass program arguments in a @SpringBootTest?

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

 java -jar myjar.jar inputFile outputFile

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

我从这个答案推断我可能必须使用 SpringApplicationBuilder 来执行此操作。

以为我有答案,但我错了。 这个不正确的信息可能对某些人仍然有用:


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

在测试运行之前应该添加到 Spring 环境中的 key=value 形式的属性。

另一个术语难题是我称之为“程序参数”的东西,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

如果你的程序参数是

--arg1=val1

在 springboot 版本 2.2.0 之前你可以使用

@SpringBootTest({"arg1=val1"})

在 springboot 2.2.0 之后你可以使用

@SpringBootTest(args={"--arg1=val1"})

我遇到过同样的问题。 开箱即用的SpringBootContextLoader (默认情况下与@SpringBootTest一起使用) 始终在不带任何参数的情况下运行您的应用程序 但是,您可以提供自己的引导程序,然后它又可以提供您自己的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 )声明要提供的参数(而不是对它们进行硬编码)。

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

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

对我来说工作的例子是

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

    @Test
    void loadContextTest() {
    }
}

与通过相同

--env test

启动Spring时的争论

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

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
    Neo4jConfigTest.class,
    FdTemplate.class,
    FdServerIo.class,
    MapBasedStorageProxy.class})
@ActiveProfiles({"dev", "fd-auth-test", "fd-client"})
public class TestEntityLinks  {

@Autowired
private ContentModelService contentModelService;

@Autowired
private BatchService batchService;

@Test
public void doSomething () { ... }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM