RU | EN | DE

1. Виды тестов

  1. Unit**-тесты** → проверяют отдельный класс (быстро, изолированно).
  2. Integration**-тесты** → проверяют взаимодействие компонентов (например, сервис + БД).
  3. 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 → только для критичных сценариев.