spring 防止 Application / CommandLineRunner 类在 JUnit 测试期间执行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29344313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:28:42  来源:igfitidea点击:

Prevent Application / CommandLineRunner classes from executing during JUnit testing

springspring-boot

提问by Gorgia666

If in your TestCase class there is this annotations:

如果在您的 TestCase 类中有此注释:

@SpringApplicationConfiguration(classes = {Application.class})

this will cause the Application.class, implementing the CommandLineRunnerinterface, to run the required method

这将导致Application.class,实现CommandLineRunner接口,运行所需的方法

public void run(String... args) throws Exception

I still think this is, mostly, a not wanted behaviour, since in your test environment you may not want to launch the entire application.

我仍然认为这主要是一种不想要的行为,因为在您的测试环境中,您可能不想启动整个应用程序。

I have in mind two solution to circumvent this problem:

我想到了两种解决方案来规避这个问题:

  1. to remove the CommandLineRunnerinterface from my Applicationclass
  2. to have a different context for testing
  1. CommandLineRunner从我的Application班级中删除界面
  2. 有不同的测试环境

Both this solution requires lot of coding. Do you have a more convenient solution?

这两种解决方案都需要大量编码。你有更方便的解决方案吗?

回答by Michael Pridemore

Jan's solution can be achieved easier.

Jan的解决方案可以更容易地实现。

In your test class, activate the "test" profile:

在您的测试类中,激活“测试”配置文件:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
public class MyFancyTest {}

In your CommandLineRunner set the profile to NOT test:

在您的 CommandLineRunner 中,将配置文件设置为不测试:

@Component
@Profile("!test")
public class JobCommandLineRunner implements CommandLineRunner {}

Then you don't have to manually set the profile in the Application.

然后您不必在应用程序中手动设置配置文件。

回答by jmgonet

As mentioned in spring documentation http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.htmlyou can use @ContextConfigurationwith a special initializer:

正如 spring 文档http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html 中提到的,您可以使用带有特殊初始化程序的@ContextConfiguration

ConfigFileApplicationContextInitializeris an ApplicationContextInitializerthat can apply to your tests to load Spring Boot application.propertiesfiles. You can use this when you don't need the full features provided by @SpringApplicationConfiguration.

ConfigFileApplicationContextInitializer是一个ApplicationContextInitializer,可以应用于您的测试以加载 Spring Boot application.properties文件。当您不需要@SpringApplicationConfiguration提供的全部功能时,您可以使用它。

In this example anyComponentis initialized and properties are injected, but run(args)methods won't be executed. (Application.classis my main spring entry point)

在此示例中,初始化了anyComponent并注入了属性,但不会执行run(args)方法。(Application.class是我的主要 spring 入口点)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, 
                      initializers = ConfigFileApplicationContextInitializer.class)
public class ExtractorTest {
    @Autowired
    AnyComponent anyComponent;

    @Test
    public void testAnyComponent() {
       anyComponent.anyMethod(anyArgument);
    }
}

回答by Bogdan Calmac

You can define a test configuration in the same package as your application that looks exactly the same, except that it excludes beans implementing CommandLineRunner. The key here is @ComponentScan.excludeFilters:

您可以在与您的应用程序相同的包中定义一个测试配置,该配置看起来完全相同,只是它不包括实现 CommandLineRunner 的 bean。这里的关键是@ComponentScan.excludeFilters:

@Configuration
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = CommandLineRunner.class))
@EnableAutoConfiguration
public class TestApplicationConfiguration {
}

Then, just replace the configuration on your test:

然后,只需替换测试中的配置:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TestApplicationConfiguration.class)
public class SomeApplicationTest {
    ...
}

No CommandLineRunner will be executed now, because they are not part of the configuration.

现在不会执行 CommandLineRunner,因为它们不是配置的一部分。

回答by jihor

I'm a bit late to the party, but a reasonable approach is to mark the bean with @ConditionalOnProperty, e.g.

我参加聚会有点晚了,但合理的方法是用 标记 bean @ConditionalOnProperty,例如

@ConditionalOnProperty(prefix = "job.autorun", name = "enabled", havingValue = "true", matchIfMissing = true)
public CommandLineRunner myRunner() {...}

The following annotation will then disable it in tests:

以下注释将在测试中禁用它:

@SpringBootTest(properties = {"job.autorun.enabled=false"})

回答by McAviti

If you have a mocking framework installed (e.g. MockMVC) you can create a mock instance of the CommandLineRunner implementation, more or less disabling it:

如果您安装了模拟框架(例如 MockMVC),您可以创建 CommandLineRunner 实现的模拟实例,或多或少地禁用它:

@MockBean private TextProcessor myProcessor;

@MockBean 私有 TextProcessor myProcessor;

回答by Jan Petzold

Previous answers didn't work wor me. I ended up using different profiles - example for the init method in Spring Boot:

以前的答案对我不起作用。我最终使用了不同的配置文件 - Spring Boot 中的 init 方法示例:

SpringApplication app = new SpringApplication(AppConfig.class);
app.setAdditionalProfiles("production");
app.run(args);

This is not executed during the tests so we're safe here.

这不会在测试期间执行,所以我们在这里是安全的。

All tests have their own profile "test" (which is useful in many other ways, too):

所有测试都有自己的配置文件“测试”(这在许多其他方面也很有用):

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
public class MyFancyTest {}

The command-line runner is annotated with the "production" profile so the tests ignore it:

命令行运行器使用“生产”配置文件进行注释,因此测试将忽略它:

@Component
@Profile("production")
public class JobCommandLineRunner implements CommandLineRunner {}

回答by Dani

I solve this by not implementing CommandLineRunner. Just get a bean from the context, and call a method on it, passing argv. That way you will get the same result, and the application won't start automatically when running the tests.

我通过不实现 CommandLineRunner 来解决这个问题。只需从上下文中获取一个 bean,并在其上调用一个方法,传递 argv。这样,您将获得相同的结果,并且在运行测试时应用程序不会自动启动。