1. Виды тестов
- Unit**-тесты** → проверяют отдельный класс (быстро, изолированно).
- Integration**-тесты** → проверяют взаимодействие компонентов (например, сервис + БД).
- End-to-End (E2E) → проверяют API целиком (через MockMvc/TestRestTemplate).
2. Unit-тесты (JUnit 5)
📄 Зависимость (обычно уже есть в spring-boot-starter-test):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>📄 Пример:
class Calculator {
int sum(int a, int b) { return a + b; }
}
class CalculatorTest {
Calculator calc = new Calculator();
@Test
void testSum() {
assertEquals(5, calc.sum(2, 3));
}
}3. Mockito (моки и стабы)
📄 Пример:
@Service
class UserService {
private final UserRepository repo;
public UserService(UserRepository repo) { this.repo = repo; }
User getById(Long id) { return repo.findById(id).orElseThrow(); }
}
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock UserRepository repo;
@InjectMocks UserService service;
@Test
void testGetById() {
User u = new User(); u.setName("Vitaliy");
when(repo.findById(1L)).thenReturn(Optional.of(u));
User result = service.getById(1L);
assertEquals("Vitaliy", result.getName());
}
}4. Spring Boot Integration Test
📄 Пример:
@SpringBootTest
class UserServiceIntegrationTest {
@Autowired UserRepository repo;
@Autowired UserService service;
@Test
void testCreateUser() {
User u = new User();
u.setName("Test");
service.createUser(u);
assertThat(repo.findByName("Test")).isNotEmpty();
}
}📌 Аннотация @SpringBootTest поднимает весь контекст Spring (медленнее, но максимально приближено к реальности).
5. MockMvc (тестирование REST API)
📄 Пример:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private UserService service;
@Test
void testGetUsers() throws Exception {
when(service.allUsers()).thenReturn(List.of(new UserDto(1L, "Vitaliy")));
mockMvc.perform(get("/api/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].name").value("Vitaliy"));
}
}📌 @WebMvcTest поднимает только веб-слой (без БД).📌 @MockBean — подменяет сервис моком.
6. TestRestTemplate (интеграционные API тесты)
📄 Пример:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserApiTest {
@Autowired TestRestTemplate restTemplate;
@Test
void testCreateUser() {
UserDto dto = new UserDto(null, "Vitaliy");
ResponseEntity<UserDto> response =
restTemplate.postForEntity("/api/users", dto, UserDto.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals("Vitaliy", response.getBody().name());
}
}7. Testcontainers (с реальной БД)
📄 Пример:
@SpringBootTest
@Testcontainers
class UserRepositoryTest {
@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("demo")
.withUsername("demo")
.withPassword("secret");
@DynamicPropertySource
static void props(DynamicPropertyRegistry reg) {
reg.add("spring.datasource.url", postgres::getJdbcUrl);
reg.add("spring.datasource.username", postgres::getUsername);
reg.add("spring.datasource.password", postgres::getPassword);
}
@Autowired UserRepository repo;
@Test
void testSaveUser() {
User u = new User();
u.setName("Vitaliy");
repo.save(u);
assertThat(repo.findByName("Vitaliy")).isNotEmpty();
}
}📌 Это максимально реалистичные интеграционные тесты.
8. H2 (In-memory DB)
Быстрая замена для dev/test. 📄 Настройка:
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password: password
h2:
console:
enabled: true📌 Открыть H2 консоль: http://localhost:8080/h2-console
9. Test Utilities
- @DataJpaTest → тестирует только JPA слой.
- @JsonTest → тестирует сериализацию/десериализацию Jackson.
- @WebMvcTest → только контроллеры.
- @SpringBootTest → весь контекст.
10. Best Practices
- ✅ Пиши юнит-тесты для бизнес-логики.
- ✅ Интеграционные тесты → для БД и API.
- ✅ Используй MockMvc для REST, а не поднимай весь сервер.
- ✅ Для сложных случаев → Testcontainers (реальная БД в Docker).
- ✅ Тесты должны быть быстрыми и изолированными.
- ✅ Уровни тестов:
- Unit → дешёвые и быстрые,
- Integration → дороже,
- E2E → только для критичных сценариев.