org.springmodules.cache.integration.AbstractIntegrationTests.java Source code

Java tutorial

Introduction

Here is the source code for org.springmodules.cache.integration.AbstractIntegrationTests.java

Source

/* 
 * Created on Oct 22, 2004
 *
 * 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 @2004 the original author or authors.
 */

package org.springmodules.cache.integration;

import java.io.Serializable;
import java.util.List;

import junit.framework.TestCase;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StringUtils;

import org.springmodules.cache.integration.KeyAndModelListCachingListener.KeyAndModel;
import org.springmodules.cache.interceptor.caching.AbstractCachingInterceptor;
import org.springmodules.cache.provider.PathUtils;
import org.springmodules.cache.util.SystemUtils;

/**
 * <p>
 * Template for test cases that verify that caching module works correctly
 * inside a Spring bean context.
 * </p>
 * 
 * @author Alex Ruiz
 * 
 * @version $Revision$ $Date$
 */
public abstract class AbstractIntegrationTests extends TestCase {

    protected static final String CACHE_MANAGER_BEAN_NAME = "cacheManager";

    private static final String ANNOTATIONS_CONTEXT = "annotationsContext.xml";

    private static final String BEAN_NAME_AUTOPROXY_CREATOR_CONTEXT = "beanNameAutoproxyCreatorContext.xml";

    private static final String CACHE_PROXY_FACTORY_BEAN_CONTEXT = "cacheProxyFactoryBeanContext.xml";

    private static final String COMMONS_ATTRIBUTES_CONTEXT = "commonsAttributesContext.xml";

    private static final String DTD_FOLDER = "/dtd/";

    private static final String SCHEMA_FOLDER = "/schema/";

    protected final Log logger = LogFactory.getLog(getClass());

    private ApplicationContext applicationContext;

    /**
     * Listener that stores the keys used to store objects in the cache. This
     * listener is used to verify that objects are being cached.
     */
    private KeyAndModelListCachingListener cachingListener;

    /**
     * Bean managed by the Spring bean context. Should be advised by the
     * interceptors that perform caching and flush the cache.
     */
    private CacheableService target;

    public AbstractIntegrationTests() {
        super();
    }

    public AbstractIntegrationTests(String name) {
        super(name);
    }

    public final void testAnnotationsWithDtd() throws Exception {
        performCachingAndFlushingWithAnnotations(DTD_FOLDER);
    }

    public final void testAnnotationsWithSchema() throws Exception {
        performCachingAndFlushingWithAnnotations(SCHEMA_FOLDER);
    }

    public final void testBeanNameAutoProxyCreatorWithDtd() throws Exception {
        performCachingAndFlushingWithBeanNameAutoProxyCreator(DTD_FOLDER);
    }

    public final void testBeanNameAutoProxyCreatorWithSchema() throws Exception {
        performCachingAndFlushingWithBeanNameAutoProxyCreator(SCHEMA_FOLDER);
    }

    public final void testCacheProxyFactoryBeanWithDtd() throws Exception {
        performCachingAndFlushingWithCacheProxyFactoryBean(DTD_FOLDER);
    }

    public final void testCacheProxyFactoryBeanWithSchema() throws Exception {
        performCachingAndFlushingWithCacheProxyFactoryBean(SCHEMA_FOLDER);
    }

    public final void testCommonsAttributesWithDtd() throws Exception {
        performCachingAndFlushingWithCommonsAttributes(DTD_FOLDER);
    }

    public final void testCommonsAttributesWithSchema() throws Exception {
        performCachingAndFlushingWithCommonsAttributes(SCHEMA_FOLDER);
    }

    protected final void assertCacheEntryFromCacheIsNull(Object cacheEntry, Serializable key) {
        assertNull("There should not be any object stored under the key <" + StringUtils.quoteIfString(key) + ">",
                cacheEntry);
    }

    protected abstract void assertCacheWasFlushed() throws Exception;

    /**
     * Asserts that the given object was cached.
     * 
     * @param expectedCachedObject
     *          the object that should have been cached.
     * @param keyAndModelIndex
     *          the index of the key/model stored in <code>cachingListener</code>.
     * @see KeyAndModelListCachingListener
     */
    protected abstract void assertObjectWasCached(Object expectedCachedObject, int keyAndModelIndex)
            throws Exception;

    protected final ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    protected final Object cacheManager() {
        return applicationContext.getBean(CACHE_MANAGER_BEAN_NAME);
    }

    protected final KeyAndModelListCachingListener getCachingListener() {
        return cachingListener;
    }

    protected final KeyAndModel getKeyAndModel(int index) {
        List keyAndModelPairs = cachingListener.getKeyAndModelPairs();
        KeyAndModel keyModel = (KeyAndModel) keyAndModelPairs.get(index);
        return keyModel;
    }

    /**
     * Verifies that the caching and the cache-flushing are working correctly.
     */
    private void performCachingAndFlushing(String configStrategyConfig) throws Exception {
        setUpApplicationContext(configStrategyConfig);

        cachingListener = (KeyAndModelListCachingListener) applicationContext.getBean("cachingListener");

        target = (CacheableService) applicationContext.getBean("cacheableService");

        logger.debug("Storing in the cache...");
        int nameIndex = 0;

        String cachedObject = target.getName(nameIndex);
        assertTrue("The retrieved name should not be empty", StringUtils.hasText(cachedObject));

        assertObjectWasCached(cachedObject, nameIndex);

        // call the same method again. This time the return value should be read
        // from the cache.
        logger.debug("Reading from the cache...");
        cachedObject = target.getName(nameIndex);

        // verify that the element was cached only once. There should be only
        // one caching event registered in the listener.
        int expectedTimesObjectWasCached = 1;
        int actualTimesObjectWasCached = cachingListener.getKeyAndModelPairs().size();
        assertEquals("<Number of times the same object was cached>", expectedTimesObjectWasCached,
                actualTimesObjectWasCached);

        // call the method 'updateName(int, String)'. When executed, the cache
        // should be flushed.
        logger.debug("Flushing the cache ...");
        target.updateName(nameIndex, "Darth Maul");

        assertCacheWasFlushed();

        // NULL_ENTRY should be cached, and null should be returned.
        target.updateName(++nameIndex, null);
        cachedObject = target.getName(nameIndex);
        assertObjectWasCached(AbstractCachingInterceptor.NULL_ENTRY, nameIndex);

        assertNull(cachedObject);
    }

    private void performCachingAndFlushingWithAnnotations(String configFolder) throws Exception {
        if (SystemUtils.atLeastJ2SE5()) {
            performCachingAndFlushing(configFolder + ANNOTATIONS_CONTEXT);
            return;
        }
        logger.info("Unable to run tests using file \"" + ANNOTATIONS_CONTEXT
                + ".\" Annotations are not supported by this version of Java");
    }

    private void performCachingAndFlushingWithBeanNameAutoProxyCreator(String configFolder) throws Exception {
        String configLocation = configFolder + BEAN_NAME_AUTOPROXY_CREATOR_CONTEXT;
        performCachingAndFlushing(configLocation);
    }

    private void performCachingAndFlushingWithCacheProxyFactoryBean(String configFolder) throws Exception {
        String configLocation = configFolder + CACHE_PROXY_FACTORY_BEAN_CONTEXT;
        performCachingAndFlushing(configLocation);
    }

    private void performCachingAndFlushingWithCommonsAttributes(String configFolder) throws Exception {
        String configLocation = configFolder + COMMONS_ATTRIBUTES_CONTEXT;
        performCachingAndFlushing(configLocation);
    }

    private void setUpApplicationContext(String configStrategyConfig) {
        String folder = configStrategyConfig.startsWith(DTD_FOLDER) ? DTD_FOLDER : SCHEMA_FOLDER;

        String root = "classpath:" + PathUtils.getPackageNameAsPath(getClass());
        String[] configLocations = { root + folder + "cacheContext.xml", root + configStrategyConfig };
        applicationContext = new ClassPathXmlApplicationContext(configLocations);
    }
}