如何使用 Junit 5 使用 Testcontainer 对 Kafka 运行集成测试

Posted

技术标签:

【中文标题】如何使用 Junit 5 使用 Testcontainer 对 Kafka 运行集成测试【英文标题】:How can I run Integration Test to Kafka with Testcontainer using Junit 5 【发布时间】:2019-12-21 20:47:57 【问题描述】:

我正在尝试为我的 Kafka 消费者编写集成测试。 我正在使用JUnit 5,所以我无法使用@Rule 对其进行初始化,而我看到的使用@Container 初始化的示例也无法正常工作。

我尝试将我的 Junit 版本更改为 Junit 4,但这会损坏我的其他测试(所以我需要继续使用 Junit 5)。

我在 Junit 4 尝试使用这个例子: https://www.testcontainers.org/modules/kafka/

还有那些Junit 5:https://www.hascode.com/2019/01/using-throwaway-containers-for-integration-testing-with-java-junit-5-and-testcontainers/

但它无法识别我的注释(@Testcontainers@Container)。

Gradle 导入:

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
implementation group: 'org.apache.kafka', name: 'kafka-clients', version: '1.1.1'
testIntegrationImplementation "org.testcontainers:kafka:1.11.4"

我将此代码作为注释上传:

@Testcontainers
public class KafkaTestContainer implements BeforeAllCallback, AfterAllCallback 

    @Container
    public KafkaContainer kafkaContainer = new KafkaContainer();
    private static final Logger logger = LoggerFactory.getLogger(KafkaTestContainer.class);

    @Inject
    private KafkaTestContainer() 
        try 

         catch (Exception e) 
            logger.error(e.getMessage());
        
    

    private String getKafkaBootstrapServers(Request request) throws IOException 
        return this.kafkaContainer.getBootstrapServers();
    


    public void stopKafkaTestContainer() 
        // Stop the container.
        kafkaContainer.stop();

    

    @Override
    public void afterAll(ExtensionContext context) throws Exception 
    

    @Override
    public void beforeAll(ExtensionContext context) throws Exception 
        boolean isKafkaRunning = this.kafkaContainer.isRunning();
        if(isKafkaRunning) 
            logger.info("start Kafka docker!!");
        
    

isKafkaRunning 值始终为 false。

    对 Kafka 测试容器初始化有任何帮助吗? 我错过了什么??

【问题讨论】:

你有解决方案了吗? 【参考方案1】:

以下是对我有用的设置:

...
<properties>
        <java.version>1.8</java.version>
        <testcontainers.version>1.14.3</testcontainers.version>
        <junit.jupiter.version>5.6.2</junit.jupiter.version>
        <lettuce.version>5.3.3.RELEASE</lettuce.version>
        <lombok.version>1.18.12</lombok.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-messaging</artifactId>
        </dependency>
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>$lettuce.version</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>$lombok.version</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- JUnit 5 dependencies -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>$junit.jupiter.version</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>$junit.jupiter.version</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>$junit.jupiter.version</version>
            <scope>test</scope>
        </dependency>

        <!-- Testcontainers dependencies -->
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>testcontainers</artifactId>
            <version>$testcontainers.version</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>$testcontainers.version</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>kafka</artifactId>
            <version>$testcontainers.version</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

测试类示例:

@SpringBootTest
@Testcontainers
class KafkaProducerTest 

    @Container
    public KafkaContainer container = new KafkaContainer();

    @Test
    void sendMessage() 
        assertTrue(container.isRunning());
    

【讨论】:

【参考方案2】:

您缺少以下依赖项:

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.13.0</version>
    <scope>test</scope>
</dependency>

【讨论】:

【参考方案3】:

当然有更复杂的方法可以做到这一点,但我认为你只需要:

    @Override
    public void beforeAll(ExtensionContext context) throws Exception 
        while(!this.kafkaContainer.isRunning());
        logger.info("start Kafka docker!!");
    

如果可行,您应该添加一个真正的异步框架,并实现更成熟的重试和超时。

【讨论】:

以上是关于如何使用 Junit 5 使用 Testcontainer 对 Kafka 运行集成测试的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Junit 5 使用 Testcontainer 对 Kafka 运行集成测试

如何在Gradle中使用JUnit 5?

Junit 5 如何使用 Guice DI

如何使用 Gradle 和 JUnit 5 仅运行特定测试?

如何使用 JUnit 5 在 Kotlin 中创建 TestContainers 基测试类

如何将 Gradle 中的原生 JUnit 5 支持与 Kotlin DSL 结合使用?