【问题标题】:How to run @SpringBatchTest with junit5 jupiter engine如何使用 junit5 jupiter 引擎运行 @SpringBatchTest
【发布时间】:2020-07-04 21:31:10
【问题描述】:

我正在按照以下链接编写端到端春季批处理作业测试。

https://docs.spring.io/spring-batch/docs/current/reference/html/testing.html#endToEndTesting

这告诉你用 @RunWith(SpringRunner.class) 注释你的测试类,这是 Junit4 的特性,我的测试用例使用 junit5 的老式引擎工作正常。

由于我的其他非批处理相关的测试用例在 jupiter 引擎上运行,我想在我的端到端春季批处理作业测试中使用相同的测试用例。如果我用@ExtendWith(SpringExtension.class) 替换@RunWith(SpringRunner.class),我可以看到没有一个自动装配的字段被实例化并且具有空值。

由于我对 spring batch 和 jupiter 都是新手,所以我无法理解出了什么问题。

任何指针将不胜感激

junit 测试用例示例代码

import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.JobRepositoryTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import static org.assertj.core.api.Assertions.assertThat;

@Slf4j
@Testcontainers
@SpringBatchTest
@SpringBootTest
@RunWith(SpringRunner.class)
//@ExtendWith(SpringExtension.class)
@ContextConfiguration(initializers = {BatchJobConfigTest.Initializer.class})
@Import({LiquibaseConfigprimary.class, LiquibaseConfigsecondary.class})
public class BatchJobConfigTest {

    @Container
    private static final PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:latest")
            .withDatabaseName("dummy-db")
            .withUsername("sa")
            .withPassword("sa");

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;
    @Autowired
    @Qualifier("primaryDatasource")
    private HikariDataSource primaryDatasource;
    @Autowired
    @Qualifier("secondaryDatasource")
    private HikariDataSource secondaryDatasource;
    @Autowired
    private SecondaryRepository secondaryRepository;   
    @Autowired
    private PrimaryRepository primaryRepository;
    @Autowired
    private JobRepositoryTestUtils jobRepositoryTestUtils;
    @Autowired
    private BatchConfigurer batchConfigurer;
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @BeforeEach
    void setup() {
        secondaryRepository.deleteAll();
        primaryRepository.deleteAll();
    }

    @Test
    public void testJob() throws Exception {
        assertThat(primaryRepository.findAll()).hasSize(1);
        assertThat(secondaryRepository.findAll()).hasSize(0);
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        assertThat(secondaryRepository.findAll()).hasSize(1);
        assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo("COMPLETED");
    }

    static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            if (!postgreSQLContainer.isRunning())
                postgreSQLContainer.start();
            TestPropertyValues.of(
                    "spring.data.postgres.url=" + postgreSQLContainer.getJdbcUrl(),
                    "spring.data.postgres.username=" + postgreSQLContainer.getUsername(),
                    "spring.data.postgres.password=" + postgreSQLContainer.getPassword(),
                    "spring.data.postgres.host=localhost",
                    "spring.data.postgres.port=" + postgreSQLContainer.getFirstMappedPort(),
                    "spring.data.postgres.database=" + postgreSQLContainer.getDatabaseName()
            ).applyTo(configurableApplicationContext.getEnvironment());

            TestPropertyValues.of(
                    "spring.datasource-secondary.jdbc-url=" + postgreSQLContainer.getJdbcUrl(),
                    "spring.datasource-secondary.username=" + postgreSQLContainer.getUsername(),
                    "spring.datasource-secondary.password=" + postgreSQLContainer.getPassword(),
                    "spring.datasource-secondary.driver-class-name=org.postgresql.Driver"
            ).applyTo(configurableApplicationContext.getEnvironment());

        }
    }

}

【问题讨论】:

  • 请出示您的代码。包含所有导入语句。
  • @johanneslink 添加代码

标签: spring-boot spring-batch junit5


【解决方案1】:

你可以摆脱@RunWith(SpringRunner.class)。无需添加 @ExtendWith(SpringExtension.class),因为 @SpringBootTest 已经添加了 - 至少在当前版本的 Spring Boot 中。

然后你要做的就是改变:

import org.junit.Test;

进入

import org.junit.jupiter.api.Test;

因为这就是告诉 JUnit 平台运行 Jupiter 测试而不是 Vintage 测试的原因。希望能解决您的问题。

【讨论】:

  • 感谢您的回答。它解决了我的问题。你能否解释一下为什么如果 RunWith by ExtendWith 没有初始化自动装配变量?
  • 使用我描述的自动装配变量的设置应该可以解决。不是吗?
  • 一切都已解决,您的解决方案非常有效。我只想知道这个解决方案背后的逻辑。为什么之前会失败,为什么现在可以工作?
  • 它失败了,因为您正在运行 JUnit4 (Vintage) 测试 (org.junit.Test) 但添加了 JUnit5 (Jupiter) 扩展。 JUnit4 runners 不适用于 Jupiter 测试,反之亦然。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
相关资源
最近更新 更多