JUnit 6 с типобезопасностью JSpecify по null
JUnit 6 принимает @NullMarked из JSpecify, делая null-контракты явными во всём Assertion API.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class UserServiceTest {
// JUnit 5: no null contracts on the API
// Can assertEquals() accept null? Check source...
// Does fail(String) allow null message? Unknown.
@Test
void findUser_found() {
// Is result nullable? API doesn't say
User result = service.findById("u1");
assertNotNull(result);
assertEquals("Alice", result.name());
}
@Test
void findUser_notFound() {
// Hope this returns null, not throws...
assertNull(service.findById("missing"));
}
}
import org.junit.jupiter.api.Test;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import static org.junit.jupiter.api.Assertions.*;
@NullMarked // all refs non-null unless @Nullable
class UserServiceTest {
// JUnit 6 API is @NullMarked:
// assertNull(@Nullable Object actual)
// assertEquals(@Nullable Object, @Nullable Object)
// fail(@Nullable String message)
@Test
void findUser_found() {
// IDE warns: findById returns @Nullable User
@Nullable User result = service.findById("u1");
assertNotNull(result); // narrows type to non-null
assertEquals("Alice", result.name()); // safe
}
@Test
void findUser_notFound() {
@Nullable User result = service.findById("missing");
assertNull(result); // IDE confirms null expectation
}
}
Явные контракты
@NullMarked в модуле JUnit 6 документирует семантику null прямо в API — читать исходный код не нужно.
Безопасность на этапе компиляции
IDE и анализаторы предупреждают при передаче null туда, где ожидается ненулевое значение, выявляя ошибки до запуска тестов.
Стандарт экосистемы
JSpecify принят Spring, Guava и другими библиотеками — единая семантика null во всём стеке.
Доступно начиная с JUnit 6.0 (октябрь 2025, требуется Java 17+)
JUnit 5 поставлялся без стандартизированных аннотаций допустимости null, поэтому разработчики вынуждены были догадываться, могут ли параметры или возвращаемые значения методов утверждения быть null. JUnit 6 принимает JSpecify для всего своего модуля: аннотация @NullMarked делает все неаннотированные типы ненулевыми по умолчанию, а @Nullable отмечает исключения. Класс Assertions явно аннотирует параметры — например, assertNull(@Nullable Object actual) и fail(@Nullable String message), — благодаря чему IDE и статические анализаторы, такие как NullAway и Error Prone, могут обнаруживать ошибки работы с null во время компиляции, а не во время выполнения.