title: @Cacheable tag seems to be being ignored during JUnit testing on Spring
body: <p>I've been having some trouble getting the @Cacheable annotations on my JUnit test scenarios. It just seems to ignore the caching completely. It works in my non-test scenario, but in testing there's no evidence its even touching the cache; no new keys, hashes, lists, nothing and no exceptions either.</p>
  
  <p>Currently the method I'm trying to test resides in my DAO and basically simulates a slow connection (which won't be slow once the cache is brought into the equation) :</p>
  
  <pre><code>@Component
  public class DAO {
      @Cacheable(value="slowRetrieval", keyGenerator="simpleKeyGenerator", cacheManager="cacheManager")
      public boolean slowRetrievalTestIdExists(long testIdValue, long pauseLength) {
          boolean response = valueExists("id", "test", testIdValue);
  
          log.info("Pausing for " + pauseLength + "ms as a part of slow DB transaction simulation");
          slowMeDown(pauseLength);
  
          return response;
      }
  
      private void slowMeDown(long pause) {
          try {
              Thread.sleep(pause);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>These are the relevant bits of my testing class. They're not commented yet, but <strong>TL;DR</strong> it runs the slowRetrievalTestIdExists method a number of times and then re-runs it using the same parameters (because it should ignore the body of the method with caching). I've already tried moving these methods into the test class with no change in results :</p>
  
  <pre><code>@RunWith(SpringJUnit4ClassRunner.class)
  @SpringApplicationConfiguration(classes={ResultsServiceApplication.class, CacheConfig.class })
  @DatabaseSetup("TestData.xml")
  @Slf4j
  public class DAOTest {
      @Autowired
      private DAO dao;
  
      @Test
      public void cacheTest() {
          log.info("Testing caching. Deliberately slow database simulations ahead! Be patient please :)");
          int maxTests = 5;
          long pause = 5000l,     //5 seconds
                  estimate, executionTime = 0;
          List&lt;Map&lt;String, Object&gt;&gt; testIds = getTestData(new String[] {"id"}, "test");
          assertNotNull("No test IDs could be retrieved to test caching", testIds);
  
          if(testIds.size() &lt; maxTests) maxTests = testIds.size();
  
          estimate = (long)maxTests * pause;
  
          log.info("Slow database simulation shouldn't take much more than " + (estimate / 1000) + " seconds to complete");
  
          for(int i = 0; i &lt; maxTests; i++) {
              Long testId = (Long)testIds.get(i).get("id");
  
              log.info("Running simulated slow database transaction " + (i + 1) + " of " + maxTests);
              boolean result = dao.slowRetrievalTestIdExists(testId, pause);
          }
  
          log.info("Slow database simulations complete (hopefully). Now re-running tests but caching should speed it up");
  
          for(int i = 0; i &lt; maxTests; i++) {
              Long testId = (Long)testIds.get(i).get("id");
  
              long start = System.currentTimeMillis();
  
              log.info("Re-running simulated slow database transaction " + (i + 1) + " of " + maxTests);
              boolean result = dao.slowRetrievalTestIdExists(testId, pause);
  
              long end = System.currentTimeMillis();
  
              executionTime += (end - start);
          }
  
          executionTime /= (long)maxTests;
  
          assertTrue("The second (supposedly cached) run took longer than the initial simulated slow run", 
                  Utilities.isGreaterThan(estimate, executionTime));
      }
  }
  </code></pre>
  
  <p>Here is the cache configuration class (because I've not been using XML-based configuration) :</p>
  
  <pre><code>@Configuration
  @EnableCaching
  public class CacheConfig { 
      @Bean
      public JedisConnectionFactory redisConnectionFactory() {
          JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
  
          // Defaults
          redisConnectionFactory.setHostName("127.0.0.1");
          redisConnectionFactory.setPort(6379);
          return redisConnectionFactory;
      }
  
      @Bean
      public RedisTemplate&lt;String, String&gt; redisTemplate(RedisConnectionFactory cf) {
          RedisTemplate&lt;String, String&gt; redisTemplate = new RedisTemplate&lt;String, String&gt;();
          redisTemplate.setConnectionFactory(cf);
  
          return redisTemplate;
      }
  
      @Primary
      @Bean
      public CacheManager cacheManager(RedisTemplate&lt;String, String&gt; redisTemplate) {
          RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
  
          cacheManager.setDefaultExpiration(300l);    //300 seconds = 5 minutes
  
          return cacheManager;
      }
  
      @Bean(name="cacheManagerLongExpiry")
      public CacheManager cacheManagerLongExpiry(RedisTemplate&lt;String, String&gt; redisTemplate) {
          RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
  
          cacheManager.setDefaultExpiration(604800l); //604,800 seconds = 1 week
  
          return cacheManager;
      }
  
      @Bean(name="cacheManagerShortExpiry")
      public CacheManager cacheManagerShortExpiry(RedisTemplate&lt;String, String&gt; redisTemplate) {
          RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
  
          cacheManager.setDefaultExpiration(43200l);  //43,200 seconds = 12 hours
  
          return cacheManager;
      }
  
      @Bean(name="simpleKeyGenerator")
        public KeyGenerator keyGenerator() {
            return new KeyGenerator() {
  
                @Override
                public Object generate(Object o, Method method, Object... objects)                     {
                  // This will generate a unique key of the class name, the method name,
                  // and all method parameters appended.
                  StringBuilder sb = new StringBuilder();
                  sb.append(o.getClass().getName());
                  sb.append(method.getName());
  
                  for (Object obj : objects) {
                      sb.append(obj.toString());
                  }
  
                  return sb.toString();
              }
          };
      }
  }
  </code></pre>
  
  <p>I would be really appreciative of any help on this as I've been at this for hours now and there's hardly anything about it on Google either.</p>