Reputation: 2668
In my Spring-Boot Web Application project I'm using Spring Cache to implement caching. Cache can be enabled/disabled by configuration key defined in application.yml
. I already have existing test cases where tests are written assuming there is no cache. So by default in my integration-test
profile caching is disabled and I initialize NoOpCacheManager
and all my tests work.
@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;
}
}
}
I also want to write tests for verification of Caching functionality. I created a CachedControllerTest
class where all the cache specific tests are written.
Problem is when I run
mvn test -Dtest=CachedControllersTest -Dspring.profiles.active=integration-test
All the tests in CachedControllerTest
class are failing because cache manager is initialized with NoOpCacheManager
even though I enabled the caching in the bean function.
I tried to create a separate profile for CachedControllerTest
and it still fails because once cacheManager
bean is initialized it is not getting reset.
mvn test -Dtest=CachedControllersTest -Dspring.profiles.active=integration-test,integration-cache-test
Here is my CachedControllerTest class
@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
My requirement is to reinitialize the cacheManage for each Test Class and CacheConfig is the bean which I want to modify at the runtime so that appropriate CacheManager
can be initialized.
In isolation if I run the CachedControllerTest
class tests they all pass because there is no other Test Class run before that which would have initialized the cacheManager to NoOpCacheManager.
Thanks in advance for any help/suggestion to make this situation work.
Edit 1
Based on the suggestion by Sam, Added @ActiveProfiles
.
Edit 2
AbstractRestControllerTest Class Definition
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class AbstractRestControllerTest {
}
Upvotes: 1
Views: 3106
Reputation: 31177
@Profile
has zero effect on a test class.
To set the active bean definition profiles for an integration test, you need to use @ActiveProfiles
from the spring-test
module.
Consult the Context configuration with environment profiles section of the Spring Reference Manual for details.
Also, CachedControllerTestsBeanConfig
must be annotated with @Configuration
not @Component
.
Regards,
Sam (author of the Spring TestContext Framework)
Upvotes: 1