/*
* Created on Feb 16, 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 @2005 the original author or authors.
*/
package org.springmodules.cache.interceptor.proxy;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.aop.Advisor;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.aop.target.EmptyTargetSource;
import org.springframework.util.ClassUtils;
import org.springmodules.cache.CachingModel;
import org.springmodules.cache.FlushingModel;
import org.springmodules.cache.integration.CacheableService;
import org.springmodules.cache.integration.CacheableServiceImpl;
import org.springmodules.cache.interceptor.caching.CachingModelSourceAdvisor;
import org.springmodules.cache.interceptor.caching.NameMatchCachingInterceptor;
import org.springmodules.cache.interceptor.flush.FlushingModelSourceAdvisor;
import org.springmodules.cache.interceptor.flush.NameMatchFlushingInterceptor;
import org.springmodules.cache.key.CacheKeyGenerator;
import org.springmodules.cache.key.HashCodeCacheKeyGenerator;
import org.springmodules.cache.mock.MockCachingModel;
import org.springmodules.cache.mock.MockFlushingModel;
import org.springmodules.cache.provider.CacheModelValidator;
import org.springmodules.cache.provider.CacheProviderFacade;
/**
* <p>
* Unit Tests for <code>{@link CacheProxyFactoryBean}</code>.
* </p>
*
* @author Alex Ruiz
*/
public final class CacheProxyFactoryBeanTests extends TestCase {
private CacheProviderFacade cacheProviderFacade;
private MockControl cacheProviderFacadeControl;
private Map cachingModels;
private CacheProxyFactoryBean factoryBean;
private Map flushingModels;
private CacheableServiceImpl target;
private CacheModelValidator validator;
private MockControl validatorControl;
public CacheProxyFactoryBeanTests(String name) {
super(name);
}
public void testAfterPropertiesSetWithCacheFlushAttributesNotSet()
throws Exception {
factoryBean = new CacheProxyFactoryBean();
setUpCachingModels();
expectAfterPropertiesSetOnCachingInterceptorOnly();
replay();
Person targetObject = new PersonImpl("Anakin", "Skywalker");
factoryBean.setTarget(targetObject);
factoryBean.afterPropertiesSet();
// verify that the target is only advised for caching.
Advised advised = (Advised) factoryBean.getProxy();
Advisor[] advisors = advised.getAdvisors();
assertEquals(1, advisors.length);
assertEquals(CachingModelSourceAdvisor.class, advisors[0].getClass());
verify();
}
public void testAfterPropertiesSetWithNullTarget() {
expectAfterPropertiesSetOnInterceptors();
replay();
try {
factoryBean.afterPropertiesSet();
fail();
} catch (IllegalStateException exception) {
// we are expecting this exception.
}
verify();
}
public void testAfterPropertiesSetWithProxyInterfacesEqualToNullAndProxyTargetClassEqualToTrue() {
expectAfterPropertiesSetOnInterceptors();
replay();
Person targetObject = new PersonImpl("Darth", "Vader");
factoryBean.setTarget(targetObject);
factoryBean.setProxyTargetClass(true);
factoryBean.afterPropertiesSet();
Advised advised = (Advised) factoryBean.getProxy();
Advisor[] advisors = advised.getAdvisors();
assertEquals(2, advisors.length);
Advisor advisor1 = advisors[0];
Advisor advisor2 = advisors[1];
if (advisor1 instanceof CachingModelSourceAdvisor) {
assertEquals(FlushingModelSourceAdvisor.class, advisor2.getClass());
} else if (advisor1 instanceof FlushingModelSourceAdvisor) {
assertEquals(CachingModelSourceAdvisor.class, advisor2.getClass());
} else {
fail("Expected: <" + CachingModelSourceAdvisor.class.getName() + "> or <"
+ FlushingModelSourceAdvisor.class.getName() + "> but was: <"
+ advisor1.getClass().getName() + ">");
}
verify();
}
public void testAfterPropertiesSetWithProxyInterfacesEqualToNullAndProxyTargetFlagEqualToFalseAndTargetInstanceOfTargetSource()
throws Exception {
expectAfterPropertiesSetOnInterceptors();
replay();
factoryBean.setProxyTargetClass(false);
Object targetInstanceOfTargetSource = EmptyTargetSource.INSTANCE;
factoryBean.setTarget(targetInstanceOfTargetSource);
try {
factoryBean.afterPropertiesSet();
fail();
} catch (AopConfigException exception) {
// we are expecting this exception.
}
verify();
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#afterPropertiesSet()}</code> creates a
* new proxy from on the given target object if the target object and the
* specified proxy interfaces are not equal to <code>null</code>.
*/
public void testAfterPropertiesSetWithProxyInterfacesNotEqualToNull()
throws Exception {
expectAfterPropertiesSetOnInterceptors();
replay();
String[] proxyInterfaces = { Person.class.getName() };
factoryBean.setProxyInterfaces(proxyInterfaces);
Person targetObject = new PersonImpl("Darth", "Vader");
factoryBean.setTarget(targetObject);
factoryBean.afterPropertiesSet();
Object proxy = factoryBean.getProxy();
assertNotNull(proxy);
Class[] targetObjectInterfaces = ClassUtils.getAllInterfaces(targetObject);
int interfacesCount = targetObjectInterfaces.length;
Class proxyClass = proxy.getClass();
for (int i = 0; i < interfacesCount; i++) {
Class targetObjectInterface = targetObjectInterfaces[i];
assertTrue("The proxy should implement the interface <"
+ targetObjectInterface.getName() + ">", targetObjectInterface
.isAssignableFrom(proxyClass));
}
assertTrue("The proxy should implement the interface <"
+ Advised.class.getName() + ">", proxy instanceof Advised);
verify();
}
/**
* Verifies that the constructor
* <code>{@link CacheProxyFactoryBean#CacheProxyFactoryBean()}</code>
* creates a new <code>{@link NameMatchFlushingInterceptor}</code> and a new
* <code>{@link NameMatchCachingInterceptor}</code>.
*/
public void testCacheProxyFactoryBean() {
assertEquals(NameMatchFlushingInterceptor.class, factoryBean
.getFlushingInterceptor().getClass());
assertEquals(NameMatchCachingInterceptor.class, factoryBean
.getCachingInterceptor().getClass());
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#createTargetSource(Object)}</code>
* returns the same object sent as argument if such argument is an instance of
* <code>org.springframework.aop.TargetSource</code>.
*/
public void testCreateTargetSourceWithTargetObjectInstanceOfTargetSource() {
Object targetObject = EmptyTargetSource.INSTANCE;
assertSame(targetObject, factoryBean.createTargetSource(targetObject));
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#createTargetSource(Object)}</code>
* creates a new <code>org.springframework.aop.TargetSource</code> setting
* the given object as its target.
*/
public void testCreateTargetSourceWithTargetObjectNotInstanceOfTargetSource()
throws Exception {
Object targetObject = new Object();
TargetSource targetSource = factoryBean.createTargetSource(targetObject);
assertSame(targetObject, targetSource.getTarget());
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#getObject()}</code> returns the
* created proxy.
*/
public void testGetObject() {
expectAfterPropertiesSetOnInterceptors();
replay();
factoryBean.setTarget(target);
factoryBean.afterPropertiesSet();
assertSame(factoryBean.getProxy(), factoryBean.getObject());
verify();
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#getObjectType()}</code> returns the
* class of the proxy if the proxy is not <code>null</code>.
*/
public void testGetObjectTypeWhenProxyIsNotNull() {
expectAfterPropertiesSetOnInterceptors();
replay();
factoryBean.setTarget(target);
factoryBean.afterPropertiesSet();
assertEquals(factoryBean.getProxy().getClass(), factoryBean.getObjectType());
verify();
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#getObjectType()}</code> returns the
* class of the target if:
* <ul>
* <li>The proxy is <code>null</code>.</li>
* <li>The target is not <code>null</code> and it is an instance of
* <code>org.springframework.aop.TargetSource</code>.</li>
* </ul>
*/
public void testGetObjectTypeWhenProxyIsNullAndTargetIsNotNullAndTargetIsInstanceOfTargetSource() {
TargetSource instanceOfTargetSource = EmptyTargetSource.INSTANCE;
factoryBean.setTarget(instanceOfTargetSource);
// verify that the proxy is null before running the method to test.
assertNull(factoryBean.getProxy());
assertEquals(instanceOfTargetSource.getClass(), factoryBean.getObjectType());
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#getObjectType()}</code> returns
* <code>null</code> if:
* <ul>
* <li>The proxy is <code>null</code>.</li>
* <li>The target is not <code>null</code> and it is not an instance of
* <code>org.springframework.aop.TargetSource</code>.</li>
* </ul>
*/
public void testGetObjectTypeWhenProxyIsNullAndTargetIsNotNullAndTargetIsNotInstanceOfTargetSource() {
factoryBean.setTarget(target);
// verify that the proxy is null before running the method to test.
assertNull(factoryBean.getProxy());
assertNull(factoryBean.getObjectType());
}
/**
* Verifies that the method
* <code>{@link CacheProxyFactoryBean#getObjectType()}</code> returns
* <code>null</code> if both the proxy and the target are <code>null</code>.
*/
public void testGetObjectTypeWhenProxyIsNullAndTargetIsNull() {
// verify that the proxy is null before running the method to test.
assertNull(factoryBean.getProxy());
assertNull(factoryBean.getObjectType());
}
/**
* Verifies that <code>{@link CacheProxyFactoryBean}</code> notifies the
* Spring IoC container that is a singleton.
*/
public void testIsSingleton() {
assertTrue(factoryBean.isSingleton());
}
public void testSetCacheKeyGenerator() {
CacheKeyGenerator keyGenerator = new HashCodeCacheKeyGenerator();
factoryBean.setCacheKeyGenerator(keyGenerator);
assertSame(keyGenerator, factoryBean.getCachingInterceptor()
.cacheKeyGenerator());
}
public void testSetFlushingModelsWithEmptyModelMap() {
assertFlushingModelSourceIsNotSetIfFlushingModelMapIsNullOrEmpty(new HashMap());
}
public void testSetFlushingModelsWithModelMapEqualToNull() {
assertFlushingModelSourceIsNotSetIfFlushingModelMapIsNullOrEmpty(null);
}
public void testSetProxyInterfaces() throws Exception {
String[] interfaceNames = new String[] { CacheableService.class.getName() };
factoryBean.setProxyInterfaces(interfaceNames);
Class[] expectedProxyInterfaces = new Class[] { CacheableService.class };
Class[] actualProxyInterfaces = factoryBean.getProxyInterfaces();
assertEquals(expectedProxyInterfaces.length, actualProxyInterfaces.length);
assertEquals(expectedProxyInterfaces[0], actualProxyInterfaces[0]);
}
protected void setUp() {
flushingModels = new HashMap();
flushingModels.put("update*", new MockFlushingModel());
factoryBean = new CacheProxyFactoryBean();
factoryBean.setFlushingModels(flushingModels);
setUpCachingModels();
target = new CacheableServiceImpl();
}
private void assertFlushingModelSourceIsNotSetIfFlushingModelMapIsNullOrEmpty(
Map models) {
assertTrue(models == null || models.isEmpty());
factoryBean.setFlushingModels(models);
assertFalse(factoryBean.isHasFlushingModels());
assertNull(factoryBean.getFlushingInterceptor().getFlushingModelSource());
}
private void expectAfterPropertiesSetOnCachingInterceptor() {
cacheProviderFacadeControl.expectAndReturn(cacheProviderFacade
.modelValidator(), validator);
for (Iterator i = cachingModels.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
CachingModel model = (CachingModel) entry.getValue();
validator.validateCachingModel(model);
}
}
private void expectAfterPropertiesSetOnCachingInterceptorOnly() {
setUpCacheModelValidator();
setUpCacheProviderFacade();
expectAfterPropertiesSetOnCachingInterceptor();
}
private void expectAfterPropertiesSetOnFlushingInterceptor() {
cacheProviderFacadeControl.expectAndReturn(cacheProviderFacade
.modelValidator(), validator);
for (Iterator i = flushingModels.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
FlushingModel model = (FlushingModel) entry.getValue();
validator.validateFlushingModel(model);
}
}
private void expectAfterPropertiesSetOnInterceptors() {
setUpCacheModelValidator();
setUpCacheProviderFacade();
expectAfterPropertiesSetOnCachingInterceptor();
expectAfterPropertiesSetOnFlushingInterceptor();
}
private void replay() {
cacheProviderFacadeControl.replay();
validatorControl.replay();
}
private void setUpCacheModelValidator() {
validatorControl = MockControl.createControl(CacheModelValidator.class);
validator = (CacheModelValidator) validatorControl.getMock();
}
private void setUpCacheProviderFacade() {
cacheProviderFacadeControl = MockControl
.createStrictControl(CacheProviderFacade.class);
cacheProviderFacade = (CacheProviderFacade) cacheProviderFacadeControl
.getMock();
factoryBean.setCacheProviderFacade(cacheProviderFacade);
}
private void setUpCachingModels() {
cachingModels = new HashMap();
cachingModels.put("get*", new MockCachingModel());
factoryBean.setCachingModels(cachingModels);
}
private void verify() {
cacheProviderFacadeControl.verify();
validatorControl.verify();
}
}