Skip to main content

Command Palette

Search for a command to run...

Bài 37: Testing với Kafka

Published
6 min readView as Markdown

Mục tiêu

Bài viết này nhằm mục tiêu hướng dẫn bạn về các phương pháp và công cụ để kiểm thử ứng dụng sử dụng Kafka. Bạn sẽ học về các loại kiểm thử trong ứng dụng Kafka, các công cụ và thư viện hỗ trợ kiểm thử, cùng với các bước thực hành để viết test case cho Producer và Consumer và sử dụng các công cụ kiểm thử để đảm bảo chất lượng ứng dụng.

Nội dung chính

1. Các loại kiểm thử trong ứng dụng sử dụng Kafka

Kiểm thử đơn vị (Unit Testing): Kiểm thử đơn vị tập trung vào việc kiểm tra các thành phần nhỏ nhất của ứng dụng, như các phương thức của Producer và Consumer. Mục tiêu là đảm bảo rằng từng thành phần hoạt động đúng như mong đợi.

Kiểm thử tích hợp (Integration Testing): Kiểm thử tích hợp kiểm tra sự tương tác giữa các thành phần khác nhau của ứng dụng, bao gồm cả việc gửi và nhận thông điệp giữa Producer và Consumer thông qua Kafka. Mục tiêu là đảm bảo rằng các thành phần hoạt động cùng nhau một cách chính xác.

Kiểm thử hệ thống (System Testing): Kiểm thử hệ thống kiểm tra toàn bộ hệ thống ứng dụng sử dụng Kafka để đảm bảo rằng tất cả các thành phần hoạt động đúng khi kết hợp với nhau. Mục tiêu là đảm bảo rằng hệ thống đáp ứng đầy đủ các yêu cầu và hoạt động như mong đợi.

Kiểm thử hiệu năng (Performance Testing): Kiểm thử hiệu năng đánh giá hiệu suất của hệ thống khi xử lý một lượng lớn dữ liệu Kafka. Mục tiêu là đảm bảo rằng hệ thống có thể xử lý tải cao mà không gặp sự cố hoặc giảm hiệu suất.

2. Các công cụ và thư viện hỗ trợ kiểm thử

JUnit: JUnit là một framework kiểm thử đơn vị phổ biến cho Java. Nó cung cấp các công cụ để viết và chạy các test case cho các thành phần của ứng dụng Kafka.

Mockito: Mockito là một framework mô phỏng (mocking) cho Java. Nó cho phép tạo các đối tượng giả để kiểm thử các thành phần của ứng dụng mà không cần phụ thuộc vào các thành phần thực tế.

Kafka Test Utils: Kafka Test Utils là một tập hợp các công cụ và tiện ích được cung cấp bởi Kafka để hỗ trợ việc kiểm thử các ứng dụng sử dụng Kafka. Nó bao gồm các lớp và phương thức để tạo các Kafka broker giả, tạo các topic và kiểm tra các thông điệp.

Testcontainers: Testcontainers là một thư viện Java cho phép tạo và quản lý các container Docker để kiểm thử tích hợp. Nó có thể được sử dụng để tạo các instance Kafka trong các container Docker để kiểm thử ứng dụng.

Thực hành

Viết test case cho Producer và Consumer

Bước 1: Cài đặt các thư viện kiểm thử Thêm các thư viện cần thiết vào file pom.xml nếu bạn sử dụng Maven:

<dependencies>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-clients</artifactId>
        <version>2.8.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka_2.12</artifactId>
        <version>2.8.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>3.9.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.testcontainers</groupId>
        <artifactId>kafka</artifactId>
        <version>1.15.3</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Bước 2: Viết test case cho Producer

  • Producer:
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.serialization.StringSerializer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.utility.DockerImageName;

import java.util.Properties;
import java.util.concurrent.ExecutionException;

import static org.junit.jupiter.api.Assertions.assertNotNull;

public class KafkaProducerTest {

    private static KafkaContainer kafkaContainer;

    @BeforeAll
    public static void setUp() {
        kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:5.4.3"));
        kafkaContainer.start();
    }

    @AfterAll
    public static void tearDown() {
        kafkaContainer.stop();
    }

    @Test
    public void testProducer() throws ExecutionException, InterruptedException {
        Properties props = new Properties();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaContainer.getBootstrapServers());
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

        KafkaProducer<String, String> producer = new KafkaProducer<>(props);
        ProducerRecord<String, String> record = new ProducerRecord<>("test-topic", "key", "value");

        RecordMetadata metadata = producer.send(record).get();
        assertNotNull(metadata);
    }
}

Bước 3: Viết test case cho Consumer

  • Consumer:
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class KafkaConsumerTest {

    private static KafkaContainer kafkaContainer;

    @BeforeAll
    public static void setUp() {
        kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:5.4.3"));
        kafkaContainer.start();
    }

    @AfterAll
    public static void tearDown() {
        kafkaContainer.stop();
    }

    @Test
    public void testConsumer() {
        Properties props = new Properties();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaContainer.getBootstrapServers());
        props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group");
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
        consumer.subscribe(Collections.singletonList("test-topic"));

        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(10000));
        assertEquals(1, records.count());

        for (ConsumerRecord<String, String> record : records) {
            assertEquals("key", record.key());
            assertEquals("value", record.value());
        }
    }
}

Sử dụng các công cụ kiểm thử để đảm bảo chất lượng ứng dụng

Bước 4: Sử dụng Mockito để mô phỏng Kafka

  • Mockito: Sử dụng Mockito để tạo các đối tượng giả cho Kafka Producer và Consumer để kiểm thử mà không cần phụ thuộc vào Kafka thực sự.
import static org.mockito.Mockito.*;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.junit.jupiter.api.Test;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import static org.junit.jupiter.api.Assertions.assertNotNull;

public class KafkaProducerMockitoTest {

    @Test
    public void testProducerWithMockito() throws ExecutionException, InterruptedException {
        KafkaProducer<String, String> producer = mock(KafkaProducer.class);
        ProducerRecord<String, String> record = new ProducerRecord<>("test-topic", "key", "value");
        Future<RecordMetadata> future = mock(Future.class);
        when(producer.send(record)).thenReturn(future);
        when(future.get()).thenReturn(new RecordMetadata(null, 0, 0, 0, 0L, 0, 0));

        RecordMetadata metadata = producer.send(record).get();
        assertNotNull(metadata);
    }
}

Câu hỏi củng cố kiến thức

Câu 1: Các loại kiểm thử phổ biến trong ứng dụng sử dụng Kafka là gì?

  • Trả lời: Các loại kiểm thử phổ biến bao gồm kiểm thử đơn vị (Unit Testing), kiểm thử tích hợp (Integration Testing), kiểm thử hệ thống (System Testing) và kiểm thử hiệu năng (Performance Testing).

Câu 2: Những công cụ và thư viện nào

hỗ trợ kiểm thử ứng dụng Kafka?

  • Trả lời: Các công cụ và thư viện hỗ trợ kiểm thử ứng dụng Kafka bao gồm JUnit, Mockito, Kafka Test Utils và Testcontainers.

Câu 3: Làm thế nào để viết test case cho Kafka Producer?

  • Trả lời: Bạn có thể viết test case cho Kafka Producer bằng cách sử dụng JUnit và Testcontainers để tạo một Kafka broker giả, sau đó kiểm tra xem Producer có gửi thông điệp đúng cách hay không.

Câu 4: Làm thế nào để viết test case cho Kafka Consumer?

  • Trả lời: Bạn có thể viết test case cho Kafka Consumer bằng cách sử dụng JUnit và Testcontainers để tạo một Kafka broker giả, sau đó kiểm tra xem Consumer có nhận và xử lý thông điệp đúng cách hay không.

Hy vọng bài viết này giúp bạn hiểu rõ hơn về các phương pháp và công cụ kiểm thử ứng dụng sử dụng Kafka và cung cấp các bước thực hành cụ thể để viết test case và sử dụng các công cụ kiểm thử để đảm bảo chất lượng ứng dụng.

More from this blog

hoangkim

366 posts