/* * Copyright 2002-2016 the original author or authors. * * 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. */ package org.springframework.cache.interceptor; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.cache.annotation.AnnotationCacheOperationSource; import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Caching; import org.springframework.cache.concurrent.ConcurrentMapCache; import org.springframework.context.expression.AnnotatedElementKey; import org.springframework.context.support.StaticApplicationContext; import org.springframework.expression.EvaluationContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.ReflectionUtils; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; /** * @author Costin Leau * @author Phillip Webb * @author Sam Brannen * @author Stephane Nicoll */ public class ExpressionEvaluatorTests { private final CacheOperationExpressionEvaluator eval = new CacheOperationExpressionEvaluator(); private final AnnotationCacheOperationSource source = new AnnotationCacheOperationSource(); private Collection<CacheOperation> getOps(String name) { Method method = ReflectionUtils.findMethod(AnnotatedClass.class, name, Object.class, Object.class); return this.source.getCacheOperations(method, AnnotatedClass.class); } @Test public void testMultipleCachingSource() throws Exception { Collection<CacheOperation> ops = getOps("multipleCaching"); assertEquals(2, ops.size()); Iterator<CacheOperation> it = ops.iterator(); CacheOperation next = it.next(); assertTrue(next instanceof CacheableOperation); assertTrue(next.getCacheNames().contains("test")); assertEquals("#a", next.getKey()); next = it.next(); assertTrue(next instanceof CacheableOperation); assertTrue(next.getCacheNames().contains("test")); assertEquals("#b", next.getKey()); } @Test public void testMultipleCachingEval() throws Exception { AnnotatedClass target = new AnnotatedClass(); Method method = ReflectionUtils.findMethod(AnnotatedClass.class, "multipleCaching", Object.class, Object.class); Object[] args = new Object[] { new Object(), new Object() }; Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test")); EvaluationContext evalCtx = this.eval.createEvaluationContext(caches, method, args, target, target.getClass(), null); Collection<CacheOperation> ops = getOps("multipleCaching"); Iterator<CacheOperation> it = ops.iterator(); AnnotatedElementKey key = new AnnotatedElementKey(method, AnnotatedClass.class); Object keyA = this.eval.key(it.next().getKey(), key, evalCtx); Object keyB = this.eval.key(it.next().getKey(), key, evalCtx); assertEquals(args[0], keyA); assertEquals(args[1], keyB); } @Test public void withReturnValue() throws Exception { EvaluationContext context = createEvaluationContext("theResult"); Object value = new SpelExpressionParser().parseExpression("#result").getValue(context); assertThat(value, equalTo("theResult")); } @Test public void withNullReturn() throws Exception { EvaluationContext context = createEvaluationContext(null); Object value = new SpelExpressionParser().parseExpression("#result").getValue(context); assertThat(value, nullValue()); } @Test public void withoutReturnValue() throws Exception { EvaluationContext context = createEvaluationContext(CacheOperationExpressionEvaluator.NO_RESULT); Object value = new SpelExpressionParser().parseExpression("#result").getValue(context); assertThat(value, nullValue()); } @Test public void unavailableReturnValue() throws Exception { EvaluationContext context = createEvaluationContext(CacheOperationExpressionEvaluator.RESULT_UNAVAILABLE); try { new SpelExpressionParser().parseExpression("#result").getValue(context); fail("Should have failed to parse expression, result not available"); } catch (VariableNotAvailableException e) { assertEquals("wrong variable name", "result", e.getName()); } } @Test public void resolveBeanReference() throws Exception { StaticApplicationContext applicationContext = new StaticApplicationContext(); BeanDefinition beanDefinition = new RootBeanDefinition(String.class); applicationContext.registerBeanDefinition("myBean", beanDefinition); applicationContext.refresh(); EvaluationContext context = createEvaluationContext(CacheOperationExpressionEvaluator.NO_RESULT, applicationContext); Object value = new SpelExpressionParser().parseExpression("@myBean.class.getName()").getValue(context); assertThat(value, is(String.class.getName())); } private EvaluationContext createEvaluationContext(Object result) { return createEvaluationContext(result, null); } private EvaluationContext createEvaluationContext(Object result, BeanFactory beanFactory) { AnnotatedClass target = new AnnotatedClass(); Method method = ReflectionUtils.findMethod(AnnotatedClass.class, "multipleCaching", Object.class, Object.class); Object[] args = new Object[] { new Object(), new Object() }; Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test")); return this.eval.createEvaluationContext(caches, method, args, target, target.getClass(), result, beanFactory); } private static class AnnotatedClass { @Caching(cacheable = { @Cacheable(value = "test", key = "#a"), @Cacheable(value = "test", key = "#b") }) public void multipleCaching(Object a, Object b) { } } }