Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring testing: Another CacheManager with same name 'myCacheManager' already exists in the same VM

Before you mark this as duplicate please read the question first. I've read all the stuff about this exception however it does not solve the issue for me. And I do get a slightly different exception eg Another CacheManager with same name 'myCacheManager' already exists instead of Another unnamed CacheManager already exists.

Spring config:

<cache:annotation-driven cache-manager="cacheManager"/>

<bean id="cacheManager"
      class="org.springframework.cache.ehcache.EhCacheCacheManager"
      p:cacheManager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
      p:configLocation="ehcache.xml"
      p:cacheManagerName="myCacheManager"
      p:shared="true"/>

ehcache

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
        updateCheck="false" name="myCacheManager">

</ehcache>

The Problem is that I have 1 (in the future more) test classes that test security. these classes also load a SecurityContext.xml

So most test classes have this annotations:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext.xml")

However the class causing the issue:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath:ApplicationContext.xml",
    "classpath:SecurityContext.xml"
})

It seems since locations are different the context is loaded again but ehcacheManager is still active from previous test.

Note: this happens only when running multiple tests (eg. like clean + build). Running this test class separately works perfectly fine.

Whats the issue? How can I solve it?

like image 307
beginner_ Avatar asked Feb 22 '13 10:02

beginner_


3 Answers

Add @DirtiesContext annotation to your test class:

@ContextConfiguration(...)
@RunWith(...)
@DirtiesContext // <== add e.g. on class level
public class MyTest {
    // ...
}

This annotation indicates that the application context associated with a test is dirty and should be closed. Subsequent tests will be supplied a new context. Works on class-level and method-level.

like image 70
jeha Avatar answered Oct 04 '22 19:10

jeha


I don't know if the question/issue are still relevent, but here's a simple/proper solution (Don't need to add @DirtiesContext in all your tests). Avoid @DirtiesContext allows you to have only one shared context for all integration tests (via run by maven for example, or run all tests in an IDE). That avoids multiple problems caused by multiple contexts started in same times.

<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
  p:configLocation="ehcache.xml"
  p:cacheManagerName="myCacheManager"
  p:shared="${ehcacheManager.shared:true}"
  p:acceptExisting:"${ehcacheManager.acceptExisting:false}"/>

In your tests (integration tests), set those properties

ehcacheManager.acceptExisting=true
ehcacheManager.shared=false

It allows Spring to create an EhcacheManager (ehcache) for each test, but if an EhcacheManager with the same name exist, Spring will just reuse it. And Spring will also not destroy/shutdown it in the context annotated with @DirtiesContext.

The idea is simple, you prevent the destroy of EhcacheManager when using @DirtiesContext.

It's applicable if you use Spring 4 and EhCache:2.5+. With Spring 3, you must an extends of EhCacheManagerFactoryBean to add these two properties.

Don't forget to clear your cache before each test :)

like image 41
khong07 Avatar answered Oct 04 '22 20:10

khong07


You can run your tests with caching disabled even if your code has methods with @Cacheable annotations.

That way you do not have to slow your test run down by marking all of your tests with @DirtiesContext.

Put the cache related Spring configurations in their own Spring config file, eg. applicationContext-cache.xml file.

Include that applicationContext-cache.xml file only when running the application live, but not in your tests.

If you specifically want to test caching, then you need the @DirtiesContext annotation.

like image 44
Tero Hagström Avatar answered Oct 04 '22 19:10

Tero Hagström