2015-04-25 3 views
1

В моем проекте веб-приложения Spring-Boot я использую Spring Cache для реализации кэширования. Кэш можно включить/отключить с помощью ключа конфигурации, определенного в application.yml. У меня уже есть тестовые примеры, когда тесты написаны, если нет кеша. Поэтому по умолчанию в моем integration-test кеширование профиля отключено, и я инициализирую NoOpCacheManager и все мои тесты работают.Мгновенное создание другого менеджера кэша в каждом тестовом классе

@Profile(value = { "default", "production", "integration-test" }) 
@Configuration 
@EnableCaching(mode = AdviceMode.ASPECTJ) 
public class CacheBeanConfig extends CachingConfigurerSupport { 

    @Autowired 
    private CacheConfig cacheConfig; 

    @Bean 
    @Override 
    public CacheManager cacheManager() { 
     if (cacheConfig.isEnabled()) { 
      System.out.println("****************Couchbase CacheBeanTestsConfig cache init.**********************"); 
      Map<String, DeclaraCouchbaseTemplate> cacheCouchTemplateMap = Maps.newHashMap(); 
      Map<String, Integer> cacheTtlMap = Maps.newHashMap(); 

      for (CacheConfig.CacheConfigParam cacheParam : cacheConfig.getCaches()) { 
       try { 
        cacheCouchTemplateMap.put(cacheParam.getName(), 
         couchbaseManager.getCouchbaseTemplate(cacheParam.getName())); 
        cacheTtlMap.put(cacheParam.getName(), cacheParam.getTtl()); 
       } catch (IOException | URISyntaxException e) { 
        throw new FaultException("Unable to get couchbase template."); 
       } 
      } 

      return new CouchbaseCacheManager(cacheCouchTemplateMap, cacheTtlMap, metricRegistry); 
     } else { 
      System.out.println("****************NoOp CacheBeanTestsConfig cache init.**********************"); 
      NoOpCacheManager noopCacheManager = new NoOpCacheManager(); 
      return noopCacheManager; 
     } 
    } 

} 

Я также хочу написать тесты для проверки функциональности кэширования. Я создал класс CachedControllerTest, где написаны все тесты, относящиеся к кешу.

Проблема заключается в том, когда я бегу

mvn test -Dtest=CachedControllersTest -Dspring.profiles.active=integration-test 

Все тесты в CachedControllerTest классе не удается, потому что диспетчер кэша инициализируется NoOpCacheManager даже если я включил кэширование в функции компонента.

Я попытался создать отдельный профиль для CachedControllerTest, и он по-прежнему терпит неудачу, потому что один раз cacheManager bean инициализирован, он не получает сброс.

mvn test -Dtest=CachedControllersTest -Dspring.profiles.active=integration-test,integration-cache-test 

Вот мой CachedControllerTest класс

@ActiveProfiles("integration-cache-test") 
@DirtiesContext 
public class CachedControllersTest extends AbstractRestControllerTest { 

    @Configuration 
    @EnableCaching(mode = AdviceMode.ASPECTJ) 
    @Profile("integration-cache-test") 
    public static class CachedControllerTestsBeanConfig { 

     @Autowired 
     private CouchbaseManager couchbaseManager; 

     @Autowired 
     private CacheConfig cacheConfig; 

     @Autowired 
     private MetricRegistry metricRegistry; 

     @Autowired 
     GlobalApplicationConfig globalAppConfig; 

     @Bean 
     public CacheManager cacheManager() { 
      System.out.println("**************** CachedControllerTestsBeanConfig EnabledCaching**********************"); 
      cacheConfig.setEnabled(true); 
      if (cacheConfig.isEnabled()) { 
       System.out.println("****************Couchbase CachedControllerTestsBeanConfig cache init.**********************"); 
       Map<String, DeclaraCouchbaseTemplate> cacheCouchTemplateMap = Maps.newHashMap(); 
       Map<String, Integer> cacheTtlMap = Maps.newHashMap(); 

       for (CacheConfig.CacheConfigParam cacheParam : cacheConfig.getCaches()) { 
        try { 
         cacheCouchTemplateMap.put(cacheParam.getName(), 
          couchbaseManager.getCouchbaseTemplate(cacheParam.getName())); 
         cacheTtlMap.put(cacheParam.getName(), cacheParam.getTtl()); 
        } catch (IOException | URISyntaxException e) { 
         throw new FaultException("Unable to get couchbase template."); 
        } 
       } 

       return new CouchbaseCacheManager(cacheCouchTemplateMap, cacheTtlMap, metricRegistry); 
      } else { 
       System.out.println("****************NoOp CachedControllerTestsBeanConfig cache init.**********************"); 
       NoOpCacheManager noopCacheManager = new NoOpCacheManager(); 
       return noopCacheManager; 
      } 
     } 

     @Bean(name = "mtlKeyGenerator") 
     public KeyGenerator keyGenerator() { 
      System.out.println("****************CachedControllerTestsBeanConfig mtlKeyGenerator.**********************"); 
      return new MultiTenantKeyGenerator(globalAppConfig.getTenantId()); 
     } 

     @Bean(name = CacheManagementConfigUtils.CACHE_ASPECT_BEAN_NAME) 
     @Role(BeanDefinition.ROLE_INFRASTRUCTURE) 
     public AnnotationGroupCacheAspect cacheAspect() { 
      AnnotationGroupCacheAspect cacheAspect = AnnotationGroupCacheAspect.aspectOf(); 
      CacheManager cacheManager = (CacheManager) StaticContextHolder.getApplicationContext().getBean("cacheManager"); 
      cacheAspect.setCacheManager(cacheManager); 

      KeyGenerator keyGenerator = (KeyGenerator) StaticContextHolder.getApplicationContext().getBean("mtlKeyGenerator"); 
      cacheAspect.setKeyGenerator(keyGenerator); 
      return cacheAspect; 
     } 
    } 

    @Component 
    public static class StaticContextHolder implements ApplicationContextAware { 

     private static ApplicationContext appContext; 

     @Override 
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
      appContext = applicationContext; 
     } 

     public static ApplicationContext getApplicationContext() { 
      return appContext; 
     } 
    } 
} 

application.yml

spring: 
    profiles: integration-test 

cache: 
    enabled: false 
--- 
spring: 
    profiles: integration-cache-test 

cache: 
    enabled: false 

Мое требование переинициализировать cacheManage для каждого класса Test и CacheConfig является боба, который я хочу изменить во время выполнения, чтобы можно было инициализировать соответствующий CacheManager.

В изоляции, если я запускаю тесты класса CachedControllerTest, все они проходят, потому что нет другого тестового класса перед тем, который инициализировал cacheManager для NoOpCacheManager.

Заранее благодарим за любую помощь/предложение, чтобы эта ситуация работала.

Edit 1

основе предложению Сэма, Добавлено @ActiveProfiles.

Edit 2

AbstractRestControllerTest Определение класса

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 
@WebAppConfiguration 
public class AbstractRestControllerTest { 
} 
+0

FYI: 'AFTER_CLASS' по умолчанию' ClassMode'. Таким образом, нет причин переопределять значение по умолчанию по умолчанию. Другими словами, достаточно пустое объявление '@ DirtiesContext' на уровне класса. –

+0

Благодарим за отзыв @SamBrannen. –

+0

Вы используете 'StaticContextHolder'? Если да, то как его собирают в виде весеннего боба - через компонентное сканирование? –

ответ

1

@Profile имеет нулевой эффект на тестовом классе.

Чтобы установить активное определение компонента профилей для интеграционного теста, вам нужно использовать @ActiveProfiles из spring-test модуля.

Подробную информацию см. В разделе справочного руководства по пружине Context configuration with environment profiles.

Кроме того, CachedControllerTestsBeanConfig должен быть аннотированный с @Configurationне@Component.

С уважением,

Сэм (автор Spring Framework TestContext)

+0

Добавлен '@ActiveProfiles (« интеграция-кеш-тест »)' на класс CachedControllerTest. Но в последующих тестовых классах используется менеджер кэша, инициализированный классом «CachedControllersTest». 'DirtiesContext' добавляется только в' @ CachedControllersTest'. Я думал о других классах тестов, которые выполняют тесты после того, как 'CachedControllersTest' будет использовать' NoOpCacheManager'. Но они терпят неудачу, потому что данные подаются из кеша, и все утверждения терпят неудачу. –

+0

Как настроен 'AbstractRestControllerTest' (и любой из его суперклассов)? Использует ли это '@ ContextConfiguration'? Использует ли она '@ SpringApplicationConfiguration 'Spring Boot? и т. д. –

+0

Как «CacheBeanTestsConfig» взял (т. е. объявил) как класс конфигурации в тестах? –

Смежные вопросы