JUnit 6 com null safety do JSpecify
O JUnit 6 adota @NullMarked do JSpecify, tornando os contratos de nulidade explícitos em toda a API de asserções.
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
}
}
Contratos explícitos
@NullMarked no módulo do JUnit 6 documenta a semântica de null diretamente na API — sem necessidade de ler o código-fonte.
Segurança em tempo de compilação
IDEs e analisadores alertam quando null é passado onde non-null é esperado, detectando bugs antes dos testes rodarem.
Padrão do ecossistema
O JSpecify é adotado pelo Spring, Guava e outros — semântica de null consistente em toda a sua stack.
Disponível desde o JUnit 6.0 (outubro de 2025, requer Java 17+)
O JUnit 5 foi lançado sem anotações de nulidade padronizadas, deixando os desenvolvedores adivinhando se parâmetros de asserção ou valores de retorno poderiam ser nulos. O JUnit 6 adota o JSpecify em todo o seu módulo — a anotação @NullMarked torna todos os tipos não anotados non-null por padrão, e @Nullable marca as exceções. A classe Assertions anota explicitamente parâmetros como assertNull(@Nullable Object actual) e fail(@Nullable String message), para que IDEs e analisadores estáticos como NullAway e Error Prone detectem uso incorreto de null em tempo de compilação em vez de em tempo de execução.