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

时间:2015-03-30 10:52:52

标签: spring spring-boot

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

@SpringApplicationConfiguration(classes = {Application.class})

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

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

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

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

  1. 从我的CommandLineRunner
  2. 中删除Application界面
  3. 具有不同的测试环境
  4. 这个解决方案都需要大量编码。 你有更方便的解决方案吗?

7 个答案:

答案 0 :(得分:38)

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

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

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

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

    My service method 
     @Transactional
     public void saveUser() {
         dao.saveUser();
     }

    My Dao method
    public void saveUser() {

    Session session = sessionFactory.withOptions().tenantIdentifier("master").openSession();
        //Transaction transaction = session.beginTransaction();
        //some dummy code to show case my problem
        User user1 = new User();
        user1.setUserName("manisha");
        user1.setPassword("password");
        user1.setFirstName("manisha first");
        user1.setLastName("manisha last");
        user1.setEmail("manisha@email.com");
        user1.setState("Active");
        user1.setTenantName("manisha");
        session.persist(user1);
        //transaction.commit();
        session.close();

}

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

答案 1 :(得分:20)

如春篇文档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);
    }
}

答案 2 :(得分:17)

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

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

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

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

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

答案 3 :(得分:12)

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

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

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

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

答案 4 :(得分:1)

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

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

这在考试期间没有执行,所以我们在这里很安全。

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

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

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

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

答案 5 :(得分:1)

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

@MockBean 私有TextProcessor myProcessor;

答案 6 :(得分:0)

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