← Kursa Dön
📄 Text · 28 min

@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.