Тестирование Java-кода с помощью Kotlin и JUnit — руководство
Kotlin полностью совместим с Java, поэтому вы можете писать тесты для Java-кода на Kotlin и запускать их вместе с существующими Java-тестами в том же проекте.
В этом руководстве вы узнаете, как:
Настроить смешанный проект Java и Kotlin для запуска тестов с помощью JUnit.
Добавить тесты на Kotlin для проверки Java-кода.
Запускать тесты с помощью Maven или Gradle.
Настройка проекта
-
В IDE клонируйте пример проекта из системы контроля версий:
https://github.com/kotlin-hands-on/kotlin-junit-sample.git
-
Перейдите в модуль
initialи изучите структуру проекта:kotlin-junit-sample/ ├── initial/ │ ├── src/ │ │ ├── main/java/ # Java source code │ │ └── test/java/ # JUnit test in Java │ ├── pom.xml # Maven configuration │ └── build.gradle.kts # Gradle configuration
Модуль
initialсодержит простое приложение Todo на Java с одним тестом. -
В той же папке откройте файл сборки и обновите его содержимое, чтобы добавить поддержку Kotlin:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-junit-complete</artifactId> <version>1.0-SNAPSHOT</version> <name>kotlin-junit-complete</name> <url>https://kotlinlang.org/docs/jvm-test-using-junit.htm</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.release>17</maven.compiler.release> <jexer.version>1.6.0</jexer.version> <kotlin.version>2.4.20</kotlin.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.junit</groupId> <artifactId>junit-bom</artifactId> <version>6.0.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> <!-- Add JUnit Jupiter engine for test runtime --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> <!-- Optionally: parameterized tests support --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.gitlab.klamonte</groupId> <artifactId>jexer</artifactId> <version>${jexer.version}</version> </dependency> </dependencies> <build> <pluginManagement><!-- Lock down plugin versions to avoid using Maven defaults (can be moved to a parent pom file) --> <plugins> <!-- Clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.4.0</version> </plugin> <!-- Default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.3.0</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>3.4.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>3.1.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>3.1.2</version> </plugin> <!-- Site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --> <plugin> <artifactId>maven-site-plugin</artifactId> <version>3.12.1</version> </plugin> <plugin> <artifactId>maven-project-info-reports-plugin</artifactId> <version>3.6.1</version> </plugin> <!-- No maven-compiler-plugin needed with Kotlin extensions --> </plugins> </pluginManagement> <plugins> <!-- Activate Kotlin Maven plugin for main and test sources --> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <extensions>true</extensions> </plugin> </plugins> </build> </project>В разделе
<properties>укажите версию Kotlin.В разделе
<dependencies>добавьте зависимости JUnit Jupiter для запуска тестов.В разделе
<build><plugins>применитеkotlin-maven-plugin, установив<extensions>в значениеtrue. Это автоматически добавляет в сборку соответствующие задачи и зависимостьkotlin-stdlib.При использовании плагина Kotlin Maven с расширениями добавлять
maven-compiler-pluginв раздел<build><pluginManagement>не требуется.
// build.gradle.kts group = "org.jetbrains.kotlin" version = "1.0-SNAPSHOT" description = "kotlin-junit-complete" java.sourceCompatibility = JavaVersion.VERSION_17 plugins { application kotlin("jvm") version "2.4.20" } kotlin { jvmToolchain(17) } application { mainClass.set("org.jetbrains.kotlin.junit.App") } repositories { mavenCentral() } dependencies { implementation("com.gitlab.klamonte:jexer:1.6.0") testImplementation(kotlin("test")) testImplementation(libs.org.junit.jupiter.junit.jupiter.api) testImplementation(libs.org.junit.jupiter.junit.jupiter.params) testRuntimeOnly(libs.org.junit.jupiter.junit.jupiter.engine) testRuntimeOnly(libs.org.junit.platform.junit.platform.launcher) } tasks.test { useJUnitPlatform() }В блоке
plugins {}добавьте плагинkotlin("jvm").Установите версию цепочки инструментов JVM, соответствующую версии Java.
В блоке
dependencies {}добавьте библиотекуkotlin.test, которая предоставляет тестовые утилиты Kotlin и интегрируется с JUnit.
Kotlin/JVM поддерживает последнюю стабильную версию JUnit — JUnit 6. Её можно найти в каталоге версий
gradle/libs.versions.toml.Если вы предпочитаете использовать каталог версий, можно также добавить туда плагин
kotlin("jvm"):# gradle/libs.versions.toml [versions] kotlin = "2.4.20" junit = "6.0.3" [libraries] org-junit-jupiter-junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" } org-junit-jupiter-junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" } org-junit-jupiter-junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" } org-junit-platform-junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" } [plugins] kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } Перезагрузите файл сборки в IDE.
Подробные инструкции по настройке файла сборки см. в разделе Настройка проекта.
Добавьте первый тест на Kotlin
Тест TodoItemTest.java в initial/src/test/java уже проверяет основные функции приложения: создание элементов, значения по умолчанию, уникальные идентификаторы и изменение состояния.
Вы можете расширить набор тестов, добавив тест на Kotlin, который проверяет поведение на уровне репозитория:
Перейдите в ту же папку с исходным кодом тестов:
initial/src/test/java.Создайте файл
TodoRepositoryTest.ktв том же пакете, что и Java-тест.-
Создайте класс теста с объявлениями полей и функцией настройки:
package org.jetbrains.kotlin.junit import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.junit.jupiter.api.DisplayName internal class TodoRepositoryTest { lateinit var repository: TodoRepository lateinit var testItem1: TodoItem lateinit var testItem2: TodoItem @BeforeEach fun setUp() { repository = TodoRepository() testItem1 = TodoItem("Task 1", "Description 1") testItem2 = TodoItem("Task 2", "Description 2") } }Аннотации JUnit в Kotlin работают так же, как и в Java.
В Kotlin ключевое слово
lateinitпозволяет объявлять свойства, не допускающие значения null, которые инициализируются позднее. Это помогает избежать необходимости использовать в тестах nullable-типы (TodoRepository?).
-
Добавьте тест в класс
TodoRepositoryTest, чтобы проверить исходное состояние репозитория и количество элементов:@Test @DisplayName("Should start with empty repository") fun shouldStartEmpty() { Assertions.assertEquals(0, repository.size()) Assertions.assertTrue(repository.all.isEmpty()) }В отличие от статического импорта в Java,
Assertionsиз Jupiter импортируется как класс и используется в качестве квалификатора для функций проверки.Вместо вызовов
.getAll()в Kotlin можно обращаться к геттерам Java как к свойствам с помощьюrepository.all.
-
Напишите ещё один тест, чтобы проверить копирование всех элементов:
@Test @DisplayName("Should return defensive copy of items") fun shouldReturnDefensiveCopy() { repository.add(testItem1) val items1 = repository.all val items2 = repository.all Assertions.assertNotSame(items1, items2) Assertions.assertThrows( UnsupportedOperationException::class.java ) { items1.clear() } Assertions.assertEquals(1, repository.size()) }Чтобы получить объект класса Java из класса Kotlin, используйте
::class.java.Сложные проверки можно разделить на несколько строк без специальных символов продолжения.
-
Добавьте тест, чтобы проверить поиск элементов по идентификатору:
@Test @DisplayName("Should find item by ID") fun shouldFindItemById() { repository.add(testItem1) repository.add(testItem2) val found = repository.getById(testItem1.id()) Assertions.assertTrue(found.isPresent) Assertions.assertEquals(testItem1, found.get()) }Kotlin легко взаимодействует с Java API
Optional. Методы-геттеры автоматически преобразуются в свойства, поэтому здесь к методуisPresent()обращаются как к свойству. -
Напишите тест, чтобы проверить механизм удаления элементов:
@Test @DisplayName("Should remove item by ID") fun shouldRemoveItemById() { repository.add(testItem1) repository.add(testItem2) val removed = repository.remove(testItem1.id()) Assertions.assertTrue(removed) Assertions.assertEquals(1, repository.size()) Assertions.assertTrue(repository.getById(testItem1.id()).isEmpty) Assertions.assertTrue(repository.getById(testItem2.id()).isPresent) } @Test @DisplayName("Should return false when removing non-existent item") fun shouldReturnFalseForNonExistentRemoval() { repository.add(testItem1) val removed = repository.remove("non-existent-id") Assertions.assertFalse(removed) Assertions.assertEquals(1, repository.size()) }В Kotlin можно объединять вызовы методов и обращения к свойствам в цепочки, например
repository.getById(id).isEmpty.
Запуск тестов
Запустите тесты на Java и Kotlin, чтобы убедиться, что проект работает как ожидается:
-
Запустите тест с помощью значка на полях редактора:

Также можно запустить все тесты проекта из папки
initialс помощью командной строки:mvn test
./gradlew test
-
Измените значение одной из переменных и проверьте, что тест работает правильно. Например, измените тест
shouldAddItemтак, чтобы он ожидал неверное количество элементов в репозитории:@Test @DisplayName("Should add item to repository") fun shouldAddItem() { repository.add(testItem1) Assertions.assertEquals(2, repository.size()) // Changed from 1 to 2 Assertions.assertTrue(repository.all.contains(testItem1)) } -
Запустите тест ещё раз и убедитесь, что он завершается с ошибкой:
Что дальше
Узнайте больше о тестировании проектов Kotlin с помощью Maven.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/jvm-test-using-junit.html