JUnit itself does not require one specific naming convention for test methods, especially in JUnit 5. A test method is recognized because it is annotated with @Test, not because of its name.
That said, good test names are crucial because they explain what behavior is being tested.
1. Test Class Naming
A common convention is to name the test class after the class being tested, followed by Test.
class CalculatorTest {
}
Examples:
| Production Class | Test Class |
|---|---|
Calculator |
CalculatorTest |
UserService |
UserServiceTest |
OrderRepository |
OrderRepositoryTest |
PasswordValidator |
PasswordValidatorTest |
This makes it easy to find the tests for a given class.
2. Test Method Naming
Test method names should describe the expected behavior.
A good test name usually answers:
What should happen, and under what conditions?
Example:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CalculatorTest {
@Test
void shouldAddTwoNumbers() {
int result = 2 + 3;
assertEquals(5, result);
}
}
The method name shouldAddTwoNumbers clearly says what behavior is expected.
3. Common Naming Styles
Style 1: shouldDoSomething
This is one of the most common modern styles.
@Test
void shouldReturnSumWhenAddingTwoNumbers() {
}
Examples:
@Test
void shouldCreateUser() {
}
@Test
void shouldRejectInvalidPassword() {
}
@Test
void shouldThrowExceptionWhenEmailIsMissing() {
}
This style is readable and works well for most tests.
Style 2: methodName_shouldExpectedBehavior_whenCondition
This style includes the method being tested, the expected result, and the condition.
@Test
void calculateTotal_shouldReturnDiscountedPrice_whenUserIsPremium() {
}
Pattern:
methodName_shouldExpectedResult_whenCondition
Examples:
@Test
void login_shouldReturnToken_whenCredentialsAreValid() {
}
@Test
void findById_shouldReturnEmpty_whenUserDoesNotExist() {
}
@Test
void register_shouldThrowException_whenEmailAlreadyExists() {
}
This is useful in larger codebases because it makes test reports very descriptive.
Style 3: given_when_then
This style follows behavior-driven development naming.
@Test
void givenValidCredentials_whenLogin_thenReturnsToken() {
}
Pattern:
givenCondition_whenAction_thenExpectedResult
Examples:
@Test
void givenEmptyCart_whenCheckout_thenThrowsException() {
}
@Test
void givenPremiumUser_whenCalculatingPrice_thenAppliesDiscount() {
}
@Test
void givenMissingEmail_whenRegisteringUser_thenValidationFails() {
}
This style is very explicit, though names can become long.
Style 4: Plain Descriptive Name
Sometimes a short descriptive name is enough.
@Test
void returnsTrueForValidPassword() {
}
@Test
void throwsExceptionForInvalidEmail() {
}
@Test
void calculatesTotalPrice() {
}
This is straightforward and readable when the test case is obvious.
4. JUnit 5 Allows Readable Display Names
JUnit 5 supports @DisplayName, which lets you use spaces and natural language in test reports.
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
class PasswordValidatorTest {
@Test
@DisplayName("Valid password should be accepted")
void shouldAcceptValidPassword() {
assertTrue(true);
}
}
The method still needs a valid Java method name, but the test output can show:
Valid password should be accepted
This is useful when you want very readable test reports.
5. Older JUnit Naming Convention
Older JUnit versions, especially JUnit 3, used method names beginning with test.
public void testAddition() {
}
In modern JUnit 5, this is not required.
This still works only if the method is properly annotated with @Test:
@Test
void testAddition() {
}
But modern naming usually prefers more descriptive names like:
@Test
void shouldAddTwoNumbers() {
}
6. Good vs. Weak Test Names
Weak names
@Test
void test1() {
}
@Test
void testUser() {
}
@Test
void checkSomething() {
}
These names do not clearly explain what is being tested.
Better names
@Test
void shouldCreateUserWhenInputIsValid() {
}
@Test
void shouldRejectUserWhenEmailIsMissing() {
}
@Test
void shouldReturnEmptyListWhenNoOrdersExist() {
}
These names explain the expected behavior.
7. Naming Tests for Exceptions
When testing exceptions, include the failure condition in the name.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
class CalculatorTest {
@Test
void shouldThrowExceptionWhenDividingByZero() {
assertThrows(ArithmeticException.class, () -> {
int result = 10 / 0;
});
}
}
Other examples:
@Test
void shouldThrowExceptionWhenEmailIsInvalid() {
}
@Test
void shouldThrowExceptionWhenUserDoesNotExist() {
}
@Test
void shouldThrowExceptionWhenPasswordIsTooShort() {
}
8. Recommended Convention
For most projects, a good default is:
shouldExpectedBehaviorWhenCondition
Example:
@Test
void shouldReturnUserWhenIdExists() {
}
@Test
void shouldReturnEmptyWhenIdDoesNotExist() {
}
@Test
void shouldThrowExceptionWhenInputIsNull() {
}
This style is:
- Easy to read
- Easy to search
- Clear in test reports
- Not tied to implementation details
Summary
In JUnit 5:
- Test classes are commonly named
ClassNameTest. - Test methods do not need to start with
test. - Test methods should describe behavior clearly.
- Common styles include:
shouldDoSomethingshouldExpectedBehaviorWhenConditionmethodName_shouldExpectedBehavior_whenConditiongivenCondition_whenAction_thenExpectedResult
- Use
@DisplayNamewhen you want more readable test output.
A good test name tells you what failed before you even open the test code.
