@SpringBootTest Integration
Birim testler tek bir sınıfı izole ederken, entegrasyon testleri birden fazla bileşenin birlikte doğru çalıştığını doğrular. @SpringBootTest, Spring Boot'un sağladığı en güçlü test anotasyonudur — tam application context'i ayağa kaldırır ve gerçek bean'leri enjekte eder.
@SpringBootTest Temelleri
@SpringBootTest
class UserIntegrationTest {
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
@Test
void shouldCreateAndRetrieveUser() {
// Gerçek service, gerçek repository, gerçek veritabanı
CreateUserRequest request = new CreateUserRequest(
"Ali", "ali@test.com", "password123");
UserDto created = userService.createUser(request);
assertNotNull(created.getId());
UserDto found = userService.getUserById(created.getId());
assertEquals("Ali", found.getName());
}
}@SpringBootTest varsayılan olarak web ortamı oluşturmaz (MOCK mode). Farklı modlar:
// Varsayılan — web ortamı yok, ApplicationContext yüklenir
@SpringBootTest
// Gerçek web sunucusu başlatır (rastgele port)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// Gerçek web sunucusu (sabit port — genellikle 8080)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
// Web ortamı mock'lanır — MockMvc kullanılabilir
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)TestRestTemplate ile HTTP Testleri
RANDOM_PORT modunda gerçek HTTP istekleri yapabilirsiniz:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserApiIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@LocalServerPort
private int port;
@Test
void shouldCreateUserViaApi() {
CreateUserRequest request = new CreateUserRequest(
"Ali", "ali@test.com", "pass123");
ResponseEntity<UserDto> response = restTemplate.postForEntity(
"/api/users", request, UserDto.class);
assertEquals(HttpStatus.CREATED, response.getStatusCode());
assertNotNull(response.getBody());
assertEquals("Ali", response.getBody().getName());
}
@Test
void shouldReturn404ForNonExistentUser() {
ResponseEntity<String> response = restTemplate.getForEntity(
"/api/users/9999", String.class);
assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
}
}@TestConfiguration — Test için Özel Bean Tanımlama
Production bean'lerini test ortamında override etmek isteyebilirsiniz:
@SpringBootTest
class NotificationIntegrationTest {
@TestConfiguration
static class TestConfig {
@Bean
public EmailService emailService() {
// Gerçek email göndermek yerine mock kullan
return mock(EmailService.class);
}
@Bean
public PaymentGateway paymentGateway() {
// Test ortamında sahte ödeme gateway'i
return new FakePaymentGateway();
}
}
@Autowired
private OrderService orderService;
@Autowired
private EmailService emailService; // TestConfig'deki mock gelir
@Test
void shouldPlaceOrderWithoutSendingRealEmail() {
orderService.placeOrder(createTestOrder());
verify(emailService).sendOrderConfirmation(any());
// Gerçek email gönderilmedi — mock kullanıldı
}
}Test Profilleri
Test ortamı için ayrı konfigürasyon dosyası kullanmak en temiz yaklaşımdır:
# src/test/resources/application-test.yml
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true
mail:
host: localhost
port: 3025 # GreenMail test SMTP
logging:
level:
org.hibernate.SQL: DEBUG@SpringBootTest
@ActiveProfiles("test") // application-test.yml kullanılır
class ProductServiceIntegrationTest {
@Autowired
private ProductService productService;
@Test
void shouldUseTestDatabase() {
// H2 in-memory veritabanı kullanılıyor
Product product = productService.create(
new CreateProductRequest("Laptop", 999.99));
assertNotNull(product.getId());
}
}Application Context Caching
Spring Boot, test performansı için application context'i cache'ler. Aynı konfigürasyondaki testler aynı context'i paylaşır:
// Bu iki test aynı context'i paylaşır — cache'den gelir
@SpringBootTest
@ActiveProfiles("test")
class UserServiceIntegrationTest { /* ... */ }
@SpringBootTest
@ActiveProfiles("test")
class ProductServiceIntegrationTest { /* ... */ }
// Bu test farklı context oluşturur — profile farklı
@SpringBootTest
@ActiveProfiles("staging")
class StagingIntegrationTest { /* ... */ }Context cache anahtarı şunlardan oluşur: @ActiveProfiles, @TestPropertySource, @ContextConfiguration, @MockBean kullanımı. @MockBean eklemek context'i kirletir ve yeniden oluşturulmasına neden olur — dikkatli kullanın.
@Transactional ile Test İzolasyonu
@SpringBootTest
@ActiveProfiles("test")
@Transactional // Her test sonrası otomatik ROLLBACK
class UserRepositoryIntegrationTest {
@Autowired
private UserRepository userRepository;
@Test
void shouldSaveUser() {
User user = new User("Ali", "ali@test.com");
User saved = userRepository.save(user);
assertNotNull(saved.getId());
// Test bitince veritabanı değişiklikleri GERİ ALINIR
}
@Test
void shouldFindByEmail() {
userRepository.save(new User("Veli", "veli@test.com"));
Optional<User> found = userRepository.findByEmail("veli@test.com");
assertTrue(found.isPresent());
// Önceki testin verisi yok — her test temiz başlar
}
}@DirtiesContext — Context Yenileme
Bazı testler context'i değiştirir (cache kirletme, bean state değiştirme). Bu durumda:
@Test
@DirtiesContext // Bu test sonrasında context yeniden oluşturulur
void shouldModifyCacheState() {
cacheManager.getCache("products").clear();
// Diğer testler etkilenmesin diye context yenilenir
}
// Sınıf seviyesinde de kullanılabilir
@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class StatefulIntegrationTest { /* ... */ }⚠️ @DirtiesContext context'i yeniden başlatır — yavaştır. Mümkünse @Transactional ile izolasyon sağlayın.
@SpringBootTest ile tam entegrasyon testi yapabilirsiniz: gerçek bean'ler, gerçek veritabanı, gerçek HTTP. Test profilleri ile ortam ayrımı, context caching ile performans ve @Transactional ile izolasyon — bu üçlü, güvenilir integration test yazımının temelidir.
AI Asistan
Sorularını yanıtlamaya hazır