/* * Created on May 3, 2005 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * Copyright @2007 the original author or authors. */ package org.springmodules.cache.provider.ehcache; import junit.framework.TestCase; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import org.easymock.AbstractMatcher; import org.easymock.classextension.MockClassControl; import org.springframework.beans.propertyeditors.StringArrayPropertyEditor; import org.springframework.util.ObjectUtils; import org.springmodules.cache.CacheException; import org.springmodules.cache.FatalCacheException; import org.springmodules.cache.provider.CacheAccessException; import org.springmodules.cache.provider.CacheModelValidator; import org.springmodules.cache.provider.CacheNotFoundException; import org.springmodules.cache.provider.ReflectionCacheModelEditor; import java.beans.PropertyEditor; import java.io.Serializable; import java.lang.reflect.Method; import java.util.Map; /** * Unit Tests for <code>{@link EhCacheFacade}</code>. * * @author Omar Irbouh * @author Alex Ruiz */ public class EhCacheFacadeTests extends TestCase { protected class ElementMatcher extends AbstractMatcher { /** * @see AbstractMatcher#argumentMatches(Object,Object) */ protected boolean argumentMatches(Object expected, Object actual) { if (!(expected instanceof Element)) { throw new IllegalArgumentException( "Element matcher only evaluates instances of <" + Element.class.getName() + ">"); } if (!(actual instanceof Element)) { return false; } return equals((Element) expected, (Element) actual); } private boolean equals(Element expected, Element actual) { if (expected == actual) { return true; } if (!ObjectUtils.nullSafeEquals(expected.getKey(), actual.getKey())) { return false; } if (!ObjectUtils.nullSafeEquals(expected.getValue(), actual.getValue())) { return false; } return true; } } private static final String CACHE_NAME = "testCache"; private static final String KEY = "key"; private Cache cache; private MockClassControl cacheControl; private EhCacheFacade cacheFacade; private CacheManager cacheManager; private EhCacheCachingModel cachingModel; private EhCacheFlushingModel flushingModel; public EhCacheFacadeTests(String name) { super(name); } /** * Verifies that the method * <code>{@link EhCacheFacade#modelValidator()}</code> returns an an * instance of <code>{@link EhCacheModelValidator}</code> not equal to * <code>null</code>. */ public void testGetCacheModelValidator() { CacheModelValidator validator = cacheFacade.modelValidator(); assertNotNull(validator); assertEquals(EhCacheModelValidator.class, validator.getClass()); } public void testGetCacheWhenCacheAccessThrowsException() { setUpCache(); // we can't mock the cache manager since it doesn't have a public // constructor. // force a NullPointerException. cacheFacade.setCacheManager(null); try { cacheFacade.getCache(CACHE_NAME); fail(); } catch (CacheAccessException exception) { Throwable cause = exception.getCause(); assertNotNull(cause); assertTrue(cause instanceof NullPointerException); } } public void testGetCacheWithExistingCache() { setUpCache(); assertSame(cacheManager.getCache(CACHE_NAME), cacheFacade .getCache(CACHE_NAME)); } public void testGetCacheWithNotExistingCache() { setUpCache(); try { cacheFacade.getCache("AnotherCache"); fail(); } catch (CacheNotFoundException exception) { // we are expecting this exception. } } public void testGetCachingModelEditor() { PropertyEditor editor = cacheFacade.getCachingModelEditor(); assertNotNull(editor); assertEquals(ReflectionCacheModelEditor.class, editor.getClass()); ReflectionCacheModelEditor modelEditor = (ReflectionCacheModelEditor) editor; assertEquals(EhCacheCachingModel.class, modelEditor.getCacheModelClass()); assertNull(modelEditor.getCacheModelPropertyEditors()); } public void testGetFlushingModelEditor() { PropertyEditor editor = cacheFacade.getFlushingModelEditor(); assertNotNull(editor); assertEquals(ReflectionCacheModelEditor.class, editor.getClass()); ReflectionCacheModelEditor modelEditor = (ReflectionCacheModelEditor) editor; assertEquals(EhCacheFlushingModel.class, modelEditor.getCacheModelClass()); Map propertyEditors = modelEditor.getCacheModelPropertyEditors(); assertEquals(1, propertyEditors.size()); assertSame(StringArrayPropertyEditor.class, propertyEditors.get("cacheNames").getClass()); } public void testIsSerializableCacheElementRequired() { assertTrue(cacheFacade.isSerializableCacheElementRequired()); } /** * Verifies that the method * <code>{@link EhCacheFacade#onFlushCache(org.springmodules.cache.FlushingModel)}</code> * flushes the cache specified in the given cache model. */ public void testOnFlushCache() throws Exception { setUpCache(); cache.put(new Element(KEY, "A Value")); cacheFacade.onFlushCache(flushingModel); Object cachedValue = cache.get(KEY); assertNull("The cache '" + CACHE_NAME + "' should be empty", cachedValue); } public void testOnFlushCacheWhenCacheAccessThrowsIllegalStateException() throws Exception { Method removeAll = getRemoveAllMethodFromCache(); setUpCacheAsMockObject(removeAll); IllegalStateException expected = new IllegalStateException(); cache.removeAll(); cacheControl.setThrowable(expected); cacheControl.replay(); try { cacheFacade.onFlushCache(flushingModel); fail(); } catch (CacheAccessException exception) { assertSame(expected, exception.getCause()); } cacheControl.verify(); } public void testOnFlushCacheWhenCacheIsNotFound() { setUpCache(); cache.put(new Element(KEY, "A Value")); flushingModel.setCacheNames("NonExistingCache"); try { cacheFacade.onFlushCache(flushingModel); fail(); } catch (CacheNotFoundException exception) { // expecting this exception. } } public void testOnFlushCacheWithModelNotHavingCacheNames() throws Exception { Method removeAll = getRemoveAllMethodFromCache(); setUpCacheAsMockObject(removeAll); cacheControl.replay(); flushingModel.setCacheNames((String[]) null); cacheFacade.onFlushCache(flushingModel); cacheControl.verify(); } /** * Verifies that the method * <code>{@link EhCacheFacade#onGetFromCache(java.io.Serializable,org.springmodules.cache.CachingModel)}</code> * retrieves, from the cache specified in the given cache model, the entry * stored under the given key. */ public void testOnGetFromCache() throws Exception { setUpCache(); String expected = "An Object"; cache.put(new Element(KEY, expected)); Object cachedObject = cacheFacade.onGetFromCache(KEY, cachingModel); assertEquals(expected, cachedObject); } // DISABLED public void tstOnGetFromCacheWhenCacheAccessThrowsCacheException() throws Exception { assertOnGetFromCacheWrapsCatchedException(new net.sf.ehcache.CacheException()); } // DISABLED public void tstOnGetFromCacheWhenCacheAccessThrowsIllegalStateException() throws Exception { assertOnGetFromCacheWrapsCatchedException(new IllegalStateException()); } public void testOnGetFromCacheWhenCacheIsNotFound() { setUpCache(); cachingModel.setCacheName("NonExistingCache"); try { cacheFacade.onGetFromCache(KEY, cachingModel); fail(); } catch (CacheNotFoundException exception) { // we are expecting this exception. } } /** * Verifies that the method * <code>{@link EhCacheFacade#onGetFromCache(java.io.Serializable,org.springmodules.cache.CachingModel)}</code> * returns <code>null</code> if the specified key does not exist in the * cache. */ public void testOnGetFromCacheWhenKeyIsNotFound() throws Exception { setUpCache(); Object cachedObject = cacheFacade.onGetFromCache("NonExistingKey", cachingModel); assertNull(cachedObject); } /** * Verifies that the method * <code>{@link EhCacheFacade#onPutInCache(java.io.Serializable,org.springmodules.cache.CachingModel,Object)}</code> * stores an entry in the cache specified in the given cache model using the * given key. */ public void testOnPutInCache() throws Exception { setUpCache(); String expected = "An Object"; cacheFacade.onPutInCache(KEY, cachingModel, expected); Object cachedObject = cache.get(KEY).getValue(); assertSame(expected, cachedObject); } // DISABLED public void tstOnPutInCacheWhenCacheAccessThrowsIllegalStateException() throws Exception { Method put = Cache.class.getMethod("put", new Class[]{Element.class}); setUpCacheAsMockObject(put); IllegalStateException expected = new IllegalStateException(); String objectToCache = "Luke"; Element element = new Element(KEY, objectToCache); cache.put(element); cacheControl.setMatcher(new ElementMatcher()); cacheControl.setThrowable(expected); cacheControl.replay(); try { cacheFacade.onPutInCache(KEY, cachingModel, objectToCache); fail(); } catch (CacheAccessException exception) { assertSame(expected, exception.getCause()); } cacheControl.verify(); } /** * Verifies that the method * <code>{@link EhCacheFacade#onPutInCache(java.io.Serializable,org.springmodules.cache.CachingModel,Object)}</code> * does not store any entry in any cache if the cache specified in the given * cache model does not exist. */ public void testOnPutInCacheWhenCacheIsNotFound() throws Exception { setUpCache(); cachingModel.setCacheName("NonExistingCache"); try { cacheFacade.onPutInCache(KEY, cachingModel, "An Object"); fail(); } catch (CacheException exception) { assertCacheExceptionIsCacheNotFoundException(exception); } } public void testOnRemoveFromCache() throws Exception { setUpCache(); cache.put(new Element(KEY, "An Object")); cacheFacade.onRemoveFromCache(KEY, cachingModel); assertNull("The element with key '" + KEY + "' should have been removed from the cache", cache.get(KEY)); } // DISABLED public void tstOnRemoveFromCacheWhenCacheAccessThrowsIllegalStateException() throws Exception { Method removeMethod = Cache.class.getDeclaredMethod("remove", new Class[]{Serializable.class}); setUpCacheAsMockObject(removeMethod); IllegalStateException expected = new IllegalStateException(); cache.remove(KEY); cacheControl.setThrowable(expected); cacheControl.replay(); try { cacheFacade.onRemoveFromCache(KEY, cachingModel); fail(); } catch (CacheAccessException exception) { assertSame(expected, exception.getCause()); } cacheControl.verify(); } public void testOnRemoveFromCacheWhenCacheIsNotFound() throws Exception { setUpCache(); cache.put(new Element(KEY, "An Object")); cachingModel.setCacheName("NonExistingCache"); try { cacheFacade.onRemoveFromCache(KEY, cachingModel); fail(); } catch (CacheException exception) { assertCacheExceptionIsCacheNotFoundException(exception); } } public void testValidateCacheManagerWithCacheManagerEqualToNull() { cacheFacade.setCacheManager(null); try { cacheFacade.validateCacheManager(); fail(); } catch (FatalCacheException exception) { // we are expecting this exception. } } /** * Verifies that the method * <code>{@link EhCacheFacade#validateCacheManager()}</code> does not throw * any exception if the cache manager is not <code>null</code>. */ public void testValidateCacheManagerWithCacheManagerNotEqualToNull() throws Exception { setUpCache(); cacheFacade.validateCacheManager(); } protected void setUp() throws Exception { cacheManager = CacheManager.create(); cachingModel = new EhCacheCachingModel(); cachingModel.setCacheName(CACHE_NAME); flushingModel = new EhCacheFlushingModel(); flushingModel.setCacheNames(CACHE_NAME); cacheFacade = new EhCacheFacade(); } protected void tearDown() { cacheManager.shutdown(); } private void assertCacheExceptionIsCacheNotFoundException( CacheException exception) { assertEquals(CacheNotFoundException.class, exception.getClass()); } private void assertOnGetFromCacheWrapsCatchedException( Exception expectedCatchedException) throws Exception { Method get = Cache.class.getDeclaredMethod("get", new Class[]{Serializable.class}); setUpCacheAsMockObject(get); cacheControl.reset(); cache.get(KEY); cacheControl.setThrowable(expectedCatchedException); cacheControl.replay(); try { cacheFacade.onGetFromCache(KEY, cachingModel); fail(); } catch (CacheAccessException cacheAccessException) { assertSame(expectedCatchedException, cacheAccessException.getCause()); } cacheControl.verify(); } private Method getRemoveAllMethodFromCache() throws Exception { return Cache.class.getMethod("removeAll", new Class[0]); } private void setUpCache() { cache = cacheManager.getCache(CACHE_NAME); cacheFacade.setCacheManager(cacheManager); } private void setUpCacheAsMockObject(Method methodToMock) throws Exception { setUpCacheAsMockObject(new Method[]{methodToMock}); } private void setUpCacheAsMockObject(Method[] methodsToMock) throws Exception { Class[] constructorTypes = new Class[]{String.class, int.class, boolean.class, boolean.class, long.class, long.class}; Object[] constructorArgs = new Object[]{CACHE_NAME, new Integer(10), new Boolean(false), new Boolean(false), new Long(300), new Long(600)}; Class classToMock = Cache.class; cacheControl = MockClassControl.createControl(classToMock, constructorTypes, constructorArgs, methodsToMock); cache = (Cache) cacheControl.getMock(); // Field field = classToMock.getDeclaredField("status"); // field.setAccessible(true); // field.set(cache, Status.STATUS_UNINITIALISED); cacheFacade.setCacheManager(cacheManager); cacheManager.removeCache(CACHE_NAME); cacheManager.addCache(cache); } }