16 Mayıs 2020 Cumartesi

SpringTest @ContextConfiguration Anotasyonu - IntegrationTest İçindir

Giriş
Şu satırı dahil ederiz.
import org.springframework.test.context.ContextConfiguration;
Not : Bu anotasyon yerine daha gelişmiş olan @SpringJUnitConfig tercih edilebilir

Bu sınıf  spring dokümantasyonunda Integration Test için kullanılır deniliyor. Çünkü gerçek bir ApplicationContext ayağa kaldırılıyor. Testte @Autowired ApplicationContext yaparsak bu nesnenin dolu geldiğini görebiliriz. Böylece artık beanleri test etmek için  @MockBean,  @SpyBean kullanmaya gerek kalmıyor

Açıklaması şöyle
@ContextConfiguration annotation defines a class level metadata that is used to determine how to load and configure the ApplicationContext. @ContextConfiguration declares the application context resource locations or annotated classes used to load the context.
Yani bu anotasyon 
1. classes alanına verilen bean'leri ApplicationContext'e ekliyor. 
2. locations alanında verilen XMl'deki bean'leri ApplicationContext'e ekliyor.  
3. initializers alanına verilen bean'leri ApplicationContext'ten önce ilklendiriyor.

Eğer test kodunun bulunduğu src paketinde ikinci bir bean'i classes alanına yazmamışsam, otomatik olarak yüklenmiyor. @SpringBootTest ile karşılattırınca Integration Test içindir demek içimden gelmiyor :)

Açıklaması şöyle
If you are familiar with the Spring Test Framework, you may be used to using @ContextConfiguration(classes=…​) in order to specify which Spring @Configuration to load. Alternatively, you might have often used nested @Configuration classes within your test.

classes Alanı
Bu alanda src paketindeki gerçek bean'ler teker teker verilebilir veya @Configuration anotasyonuna sahip bean'ler verilebilir. İkinci kullanım daha pratik olabilir.

Örnek - Tek Bean
Şöyle yaparız.
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = MyBean.class)
class MyBeanTest {

  @MockBean
  EntityManager entityManager;

  @Autowired
  MyBean mybean;


  @Test
  void saveTest(){
    mybean.save();
    Mockito.verify(entityManager,Mockito.atLeastOnce()).merge.(Mockito.any());
  }
}
Örnek - @Configuration Anotasyonuna Sahip Bean
Elimizde şöyle bir kod olsun.
@Configuration
@ComponentScan(basePackages = "com.test.spring")
public class TestApplication {
}
TestApplication içinde bir bean'i test etmek için şöyle yaparız
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestApplication.class)
public class Test {
 ...
}
Örnek - - @Configuration Anotasyonuna Sahip Bean
Şöyle yaparız.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CacheableTest.CacheConfigurations.class)
public class CacheableTest {

  public static class Customer {
    ...
  }
  final public static AtomicInteger cacheableCalled = new AtomicInteger(0);
  final public static AtomicInteger cachePutCalled = new AtomicInteger(0);

  public static class CustomerCachedService {
    @Cacheable("CustomerCache")
    public Customer cacheable(String v) {
      cacheableCalled.incrementAndGet();
      return new Customer(v, "Cacheable " + v);
    }
    @CachePut("CustomerCache")
    public Customer cachePut(String b) {
      cachePutCalled.incrementAndGet();
      return new Customer(b, "Cache put " + b);
    }
  }
  @Configuration
  @EnableCaching()
  public static class CacheConfigurations {
    @Bean
    public CustomerCachedService customerCachedService() {
      return new CustomerCachedService();
    }
    @Bean
    public CacheManager cacheManager() {
      return new GuavaCacheManager("CustomerCache");
    }
  }
  @Autowired
  public CustomerCachedService cachedService;
  ...
}
Aynı sınıfta testleri şöyle yaparız.
@Test
public void testCacheable() {
  for(int i = 0; i < 1000; i++) {
    cachedService.cacheable("A");
  }
  Assert.assertEquals(cacheableCalled.get(), 1);
}

@Test
public void testCachePut() {
  for(int i = 0; i < 1000; i++) {
    cachedService.cachePut("B");
  }
  Assert.assertEquals(cachePutCalled.get(), 1000);
}
initializers Alanı
Spring context başlamadan önce çalışır. Test için kod çalıştırabilmeyi sağlar.
Örnek
Elimizde şöyle bir kod olsun. org.springframework.boot.test.util.TestPropertyValues
static class Initializer implements
  ApplicationContextInitializer<ConfigurableApplicationContext> {

  @Override
  public void initialize(ConfigurableApplicationContext configurableApplicationContext) {

    // initialize...
    TestPropertyValues
    //here you can add properties to connect...
    .of("some.property.key=some.property.value")
    .applyTo(configurableApplicationContext.getEnvironment());
  }
}
Şöyle yaparız.
@ContextConfiguration(initializers = Initializer.class)
locations Alanı
Yüklenecek bean'leri XML olarak belirtmeye yarar. value alanı ile aynıdır. String[] olarak tanımlanır.
Örnek
Şöyle yaparız.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext_test.xml" })
public class Test{
  @Autowired
  Foo foo;

  @Test
  public void checkOne(){
    System.out.println(foo.getBar());
  }
}

Hiç yorum yok:

Yorum Gönder