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

Gor*_*666 56 spring spring-boot

如果在TestCase类中有这样的注释:

@SpringApplicationConfiguration(classes = {Application.class})
Run Code Online (Sandbox Code Playgroud)

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

public void run(String... args) throws Exception
Run Code Online (Sandbox Code Playgroud)

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

我想到了解决这个问题的两个解决方案:

  1. CommandLineRunner从我的Application班级中删除界面
  2. 有不同的测试环境

这个解决方案都需要大量的编码.你有更方便的解决方案吗?

Mic*_*ore 45

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

在您的测试类中,激活"test"配置文件:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
public class MyFancyTest {}
Run Code Online (Sandbox Code Playgroud)

在CommandLineRunner中,将配置文件设置为NOT test:

@Component
@Profile("!test")
public class JobCommandLineRunner implements CommandLineRunner {}
Run Code Online (Sandbox Code Playgroud)

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

  • 仅为了使其可测试而更改生产代码并不是一个好主意。甚至配置文件名称“!test”也是经过验证的生产代码的模仿。 (3认同)

jmg*_*net 23

如Spring文档http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html中所述,您可以将@ContextConfiguration与特殊初始值设定项一起使用:

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

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

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

    @Test
    public void testAnyComponent() {
       anyComponent.anyMethod(anyArgument);
    }
}
Run Code Online (Sandbox Code Playgroud)


Bog*_*mac 21

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

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

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

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TestApplicationConfiguration.class)
public class SomeApplicationTest {
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这个答案非常聪明,它只是错过了一点:你还必须在`excludeFilters`属性中排除`Application.class`,否则它将扫描你试图排除的bean. (4认同)
  • `SpringApplicationConfiguration` @deprecated 从 1.4 开始支持 `SpringBootTest`。可以替换为`@SprinBootTest(classes = TestApplicationConfiguration.class)` (2认同)
  • 排除Application.class还将排除您可能/可能不需要的所有bean。 (2认同)

jih*_*hor 16

我参加派对有点晚了,但合理的做法是用豆子标记@ConditionalOnProperty,例如

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

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

@SpringBootTest(properties = {"job.autorun.enabled=false"})
Run Code Online (Sandbox Code Playgroud)


小智 6

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

@MockBean 私有 TextProcessor myProcessor;


小智 2

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