View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.cache.interceptor;
18  
19  import java.lang.reflect.Method;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.Iterator;
23  
24  import org.junit.Test;
25  
26  import org.springframework.cache.annotation.AnnotationCacheOperationSource;
27  import org.springframework.cache.annotation.Cacheable;
28  import org.springframework.cache.annotation.Caching;
29  import org.springframework.cache.concurrent.ConcurrentMapCache;
30  import org.springframework.expression.EvaluationContext;
31  import org.springframework.expression.spel.standard.SpelExpressionParser;
32  import org.springframework.util.ReflectionUtils;
33  
34  import static org.hamcrest.Matchers.*;
35  import static org.junit.Assert.*;
36  
37  /**
38   * @author Costin Leau
39   * @author Phillip Webb
40   * @author Sam Brannen
41   * @author Stephane Nicoll
42   */
43  public class ExpressionEvaluatorTests {
44  
45  	private ExpressionEvaluator eval = new ExpressionEvaluator();
46  
47  	private AnnotationCacheOperationSource source = new AnnotationCacheOperationSource();
48  
49  	private Collection<CacheOperation> getOps(String name) {
50  		Method method = ReflectionUtils.findMethod(AnnotatedClass.class, name, Object.class, Object.class);
51  		return source.getCacheOperations(method, AnnotatedClass.class);
52  	}
53  
54  	@Test
55  	public void testMultipleCachingSource() throws Exception {
56  		Collection<CacheOperation> ops = getOps("multipleCaching");
57  		assertEquals(2, ops.size());
58  		Iterator<CacheOperation> it = ops.iterator();
59  		CacheOperation next = it.next();
60  		assertTrue(next instanceof CacheableOperation);
61  		assertTrue(next.getCacheNames().contains("test"));
62  		assertEquals("#a", next.getKey());
63  		next = it.next();
64  		assertTrue(next instanceof CacheableOperation);
65  		assertTrue(next.getCacheNames().contains("test"));
66  		assertEquals("#b", next.getKey());
67  	}
68  
69  	@Test
70  	public void testMultipleCachingEval() throws Exception {
71  		AnnotatedClass target = new AnnotatedClass();
72  		Method method = ReflectionUtils.findMethod(AnnotatedClass.class, "multipleCaching", Object.class,
73  				Object.class);
74  		Object[] args = new Object[] { new Object(), new Object() };
75  		Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test"));
76  
77  		EvaluationContext evalCtx = eval.createEvaluationContext(caches, method, args, target, target.getClass());
78  		Collection<CacheOperation> ops = getOps("multipleCaching");
79  
80  		Iterator<CacheOperation> it = ops.iterator();
81  
82  		MethodCacheKey key = new MethodCacheKey(method, AnnotatedClass.class);
83  
84  		Object keyA = eval.key(it.next().getKey(), key, evalCtx);
85  		Object keyB = eval.key(it.next().getKey(), key, evalCtx);
86  
87  		assertEquals(args[0], keyA);
88  		assertEquals(args[1], keyB);
89  	}
90  
91  	@Test
92  	public void withReturnValue() throws Exception {
93  		EvaluationContext context = createEvaluationContext("theResult");
94  		Object value = new SpelExpressionParser().parseExpression("#result").getValue(context);
95  		assertThat(value, equalTo((Object) "theResult"));
96  	}
97  
98  	@Test
99  	public void withNullReturn() throws Exception {
100 		EvaluationContext context = createEvaluationContext(null);
101 		Object value = new SpelExpressionParser().parseExpression("#result").getValue(context);
102 		assertThat(value, nullValue());
103 	}
104 
105 	@Test
106 	public void withoutReturnValue() throws Exception {
107 		EvaluationContext context = createEvaluationContext(ExpressionEvaluator.NO_RESULT);
108 		Object value = new SpelExpressionParser().parseExpression("#result").getValue(context);
109 		assertThat(value, nullValue());
110 	}
111 
112 	@Test
113 	public void unavailableReturnValue() throws Exception {
114 		EvaluationContext context = createEvaluationContext(ExpressionEvaluator.RESULT_UNAVAILABLE);
115 		try {
116 			new SpelExpressionParser().parseExpression("#result").getValue(context);
117 			fail("Should have failed to parse expression, result not available");
118 		}
119 		catch (VariableNotAvailableException e) {
120 			assertEquals("wrong variable name", "result", e.getName());
121 		}
122 	}
123 
124 	private EvaluationContext createEvaluationContext(Object result) {
125 		AnnotatedClass target = new AnnotatedClass();
126 		Method method = ReflectionUtils.findMethod(AnnotatedClass.class, "multipleCaching", Object.class,
127 				Object.class);
128 		Object[] args = new Object[] { new Object(), new Object() };
129 		Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test"));
130 		EvaluationContext context = eval.createEvaluationContext(caches, method, args, target, target.getClass(), result);
131 		return context;
132 	}
133 
134 
135 	private static class AnnotatedClass {
136 
137 		@Caching(cacheable = { @Cacheable(value = "test", key = "#a"), @Cacheable(value = "test", key = "#b") })
138 		public void multipleCaching(Object a, Object b) {
139 		}
140 	}
141 
142 }