Maven не видит JUnit тесты: 5 способов исправить проблему
Для кого эта статья:
- Java-разработчики
- Инженеры тестирования и DevOps
Студенты и начинающие программисты, изучающие JUnit и Maven
🧪 Ощущение беспомощности, когда видишь сообщение "No tests executed" после тщательной работы над JUnit тестами — знакомо многим Java-разработчикам. Причины могут варьироваться от неправильной структуры проекта до конфликтов версий Maven и JUnit. Особенно обидно, когда локально тесты работают, а в CI-среде внезапно перестают запускаться. Разберемся, почему Maven иногда "не видит" ваши JUnit тесты и как это исправить пятью проверенными способами.
Столкнулись с проблемой запуска тестов в Maven? На Курсе Java-разработки от Skypro вы научитесь не только грамотно писать тесты, но и настраивать полноценную сборку проектов с помощью Maven. Опытные наставники помогут избежать типичных ошибок в конфигурации и подготовят вас к работе над реальными enterprise-проектами, где качественное тестирование — обязательный критерий успеха.
Проблема «No tests executed» при запуске JUnit в Maven
Сообщение "No tests executed" при запуске команды mvn test указывает на то, что Maven не смог найти и выполнить ни один тестовый класс в вашем проекте. Это не обязательно означает, что тесты не существуют — просто Maven их "не видит" из-за различных конфигурационных проблем.
Основные причины, по которым Maven может пропускать тесты:
- Неверное размещение тестовых классов в структуре проекта
- Несоответствие нейминг-паттернам, которые Maven использует для идентификации тестов
- Проблемы в конфигурации maven-surefire-plugin
- Отсутствие или несовместимость зависимостей JUnit
- Кэширование или конфликты версий
Диагностировать проблему можно, запустив Maven в режиме отладки:
mvn -X test
Это предоставит подробный лог, который поможет определить, почему тесты не выполняются. Обратите внимание на разделы, связанные с surefire-plugin и поиском тестовых классов.
| Признак проблемы | Возможная причина | Решение |
|---|---|---|
| No tests to run | Maven не нашёл классы, соответствующие тестовым шаблонам | Проверить структуру проекта и нейминг тестов |
| No test compiled | Проблемы с компиляцией тестовых классов | Проверить зависимости JUnit и совместимость версий |
| Tests run: 0, Failures: 0, Errors: 0, Skipped: 0 | Тесты найдены, но ни один не соответствует критериям запуска | Настроить корректные include/exclude паттерны в maven-surefire-plugin |
Александр Петров, ведущий DevOps-инженер
Недавно наша команда столкнулась с проблемой при интеграции проекта в Jenkins-пайплайн. Билд проходил успешно, но тесты не выполнялись — Maven сообщал "No tests executed". Локально всё работало отлично. После часов отладки мы выяснили, что CI-сервер использовал кэшированные зависимости с устаревшей версией JUnit, несовместимой с нашими тестами. Решение оказалось простым: мы добавили этап очистки кэша Maven перед сборкой. Мораль: никогда не доверяйте кэшу в автоматизированных системах сборки.

Структура проекта Maven для правильного размещения тестов
Первый шаг к решению проблемы "No tests executed" — проверка структуры проекта. Maven следует принципу "Convention over Configuration", ожидая определённое расположение файлов. 📁
Стандартная структура Maven-проекта для тестов:
src/main/java— исходный код приложенияsrc/test/java— код тестов (JUnit и другие тесты)src/test/resources— ресурсы, необходимые для тестирования
Одна из самых распространённых ошибок — помещение тестовых классов в src/main/java вместо src/test/java. В этом случае Maven не будет рассматривать их как тесты, даже если они содержат аннотации JUnit.
Важно также соблюдать правильную структуру пакетов. Тестовые классы должны быть в тех же пакетах, что и тестируемые классы, но в директории src/test/java. Например, если класс находится в src/main/java/com/example/MyClass.java, его тест должен быть в src/test/java/com/example/MyClassTest.java.
Конвенции именования тестовых классов:
| Шаблон имени | Поддержка по умолчанию | Примечание |
|---|---|---|
| *Test.java | Да | Класс должен заканчиваться на "Test", например, UserServiceTest.java |
| Test*.java | Да | Класс должен начинаться с "Test", например, TestUserService.java |
| *Tests.java | Нет | Требует дополнительной конфигурации surefire-plugin |
| *TestCase.java | Да | Класс должен заканчиваться на "TestCase", например, UserServiceTestCase.java |
Пример правильной структуры проекта:
project-root/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/
│ │ │ ├── service/
│ │ │ │ └── UserService.java
│ │ │ └── model/
│ │ │ └── User.java
│ │ └── resources/
│ └── test/
│ ├── java/
│ │ └── com/example/
│ │ ├── service/
│ │ │ └── UserServiceTest.java
│ │ └── model/
│ │ └── UserTest.java
│ └── resources/
│ └── test-data.json
└── target/
Для проверки корректности структуры проекта используйте команду:
mvn help:effective-pom
Это покажет эффективную конфигурацию POM, учитывающую все наследования и дополнения, что поможет выявить возможные проблемы с директориями.
Настройка maven-surefire-plugin для обнаружения тестов
Maven использует плагин surefire для запуска JUnit тестов. Если тесты не выполняются, возможно, требуется дополнительная настройка этого плагина в файле pom.xml. 🔧
Базовая конфигурация maven-surefire-plugin выглядит так:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
</plugin>
Если ваши тесты не соответствуют стандартным нейминг-паттернам, необходимо указать их явно:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<includes>
<include>**/*Tests.java</include>
<include>**/*Spec.java</include>
<!-- Стандартные паттерны будут добавлены автоматически -->
</includes>
</configuration>
</plugin>
Для исключения определённых тестов используйте паттерны exclude:
<configuration>
<excludes>
<exclude>**/integration/**/*.java</exclude>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
Если вы используете JUnit 5 (Jupiter), необходимо убедиться в наличии соответствующего провайдера для surefire:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
</dependency>
</dependencies>
</plugin>
Распространённые проблемы и их решения:
- Отсутствие JUnit в classpath: убедитесь, что зависимости JUnit добавлены в секцию dependencies pom.xml
- Смешивание разных версий JUnit: используйте одну версию JUnit во всем проекте
- Тайм-ауты тестов: увеличьте тайм-ауты, если ваши тесты требуют больше времени:
<configuration>
<forkedProcessTimeoutInSeconds>300</forkedProcessTimeoutInSeconds>
</configuration>
- Ограничения памяти: настройте параметры JVM, если ваши тесты требуют больше памяти:
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
</configuration>
Для отладки конфигурации surefire можно использовать параметр printSummary:
<configuration>
<printSummary>true</printSummary>
</configuration>
Наталья Соколова, TeamLead Java-разработки
Разрабатывая микросервисную архитектуру, мы столкнулись с проблемой — интеграционные тесты не запускались на CI-сервере, хотя все модульные тесты работали корректно. Maven выдавал "No tests executed" для определённых модулей. Выяснилось, что наш подход к именованию был нестандартным — мы использовали суффикс "IT" для интеграционных тестов. После добавления соответствующего include-паттерна в maven-surefire-plugin, проблема исчезла. Этот опыт научил нас всегда явно конфигурировать паттерны для тестовых классов, особенно в проектах с нестандартными соглашениями об именовании.
Типичные ошибки в зависимостях JUnit в pom.xml
Неправильные или отсутствующие зависимости JUnit в файле pom.xml — частая причина сообщения "No tests executed". Maven должен знать, какую версию JUnit использовать и как запускать тесты. 📚
Для JUnit 4 необходимо добавить следующую зависимость:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
Для JUnit 5 (Jupiter) конфигурация будет другой:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
Особое внимание стоит уделить атрибуту scope. Для тестовых зависимостей он должен быть установлен как test, чтобы Maven понимал, что эти библиотеки используются только для тестирования.
Типичные ошибки с зависимостями:
- Отсутствие явного указания версии: всегда указывайте версию JUnit, чтобы избежать использования неподходящей версии из родительского POM
- Использование устаревших версий: обновляйте JUnit до актуальных версий (4.13.2 для JUnit 4 или 5.9.2+ для JUnit 5)
- Смешивание JUnit 4 и JUnit 5: это может привести к конфликтам. Если необходимо использовать оба, примените специальный мост:
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
- Отсутствие junit-engine: для JUnit 5 недостаточно только junit-jupiter-api, нужен также junit-jupiter-engine
- Конфликты с другими тестовыми фреймворками: если вы используете TestNG или другие фреймворки, могут возникнуть конфликты
Проверка и устранение проблем с зависимостями:
mvn dependency:tree
Эта команда отобразит дерево зависимостей проекта, помогая выявить конфликты или отсутствующие библиотеки. Обратите внимание на предупреждения о дублировании или исключении зависимостей.
Для управления версиями зависимостей в многомодульных проектах рекомендуется использовать управление зависимостями:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
Это обеспечит согласованность версий JUnit во всех модулях проекта.
Сброс кэша Maven и решение конфликтов версий
Иногда проблема "No tests executed" возникает из-за кэшированных зависимостей или конфликтов версий в локальном репозитории Maven. В таких случаях требуется сброс кэша и чистая сборка. 🧹
Основные команды для сброса кэша Maven:
mvn clean
Удаляет директорию target/ с скомпилированными классами
mvn dependency:purge-local-repository
Удаляет кэшированные зависимости проекта из локального репозитория
mvn clean install -U
Флаг -U заставляет Maven проверять обновления для всех зависимостей
В некоторых случаях может потребоваться полная очистка локального репозитория Maven. Это радикальная мера, которую следует использовать с осторожностью:
rm -rf ~/.m2/repository/
Linux/MacOS
rd /s /q %USERPROFILE%\.m2\repository
Windows
Более безопасный подход — удалить только проблемные зависимости:
rm -rf ~/.m2/repository/org/junit
Распространённые проблемы с кэшем и версиями:
- Поврежденные JAR-файлы: иногда файлы в кэше могут быть загружены не полностью или повреждены
- "Застрявшие" SNAPSHOT-версии: Maven может использовать устаревшие SNAPSHOT-версии вместо обновления
- Конфликты версий транзитивных зависимостей: когда разные библиотеки требуют разных версий одной зависимости
- Проблемы с сетевыми прокси или зеркалами репозиториев: могут привести к неполной загрузке зависимостей
Для выявления конфликтов версий используйте плагин enforcer:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Запустите его командой:
mvn enforcer:enforce
Для исключения транзитивных зависимостей, вызывающих конфликты, используйте элемент exclusions:
<dependency>
<groupId>org.example</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
Создание профиля Maven для тестирования может помочь изолировать проблемы с тестами:
<profiles>
<profile>
<id>clean-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<delete dir="${user.home}/.m2/repository/org/junit" />
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Затем активировать профиль:
mvn clean test -Pclean-tests
Тщательная настройка Maven и JUnit — ключ к стабильному процессу непрерывной интеграции. Если Maven не находит ваши JUnit тесты, проверьте сначала структуру проекта и расположение тестовых классов, затем настройте maven-surefire-plugin под ваши паттерны именования. Убедитесь в корректности зависимостей JUnit и их совместимости с другими библиотеками. При сохранении проблемы выполните очистку кэша Maven. Помните, что правильно настроенная тестовая среда — это инвестиция в качество вашего кода и экономия времени в долгосрочной перспективе.