From e51da28897ddb8a1375de588e49eac58a7e392c4 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 11 Mar 2015 18:59:32 +0100 Subject: [PATCH] Polishing Issue: SPR-12803 --- .../expression/spel/ExpressionTestCase.java | 357 ++++++++---------- .../spel/MethodInvocationTests.java | 267 +++++++------ .../expression/spel/TestScenarioCreator.java | 44 +-- 3 files changed, 300 insertions(+), 368 deletions(-) diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionTestCase.java b/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionTestCase.java index 74d5aa8e12..5bb0076275 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionTestCase.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -16,9 +16,6 @@ package org.springframework.expression.spel; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - import java.util.Arrays; import java.util.List; @@ -29,6 +26,8 @@ import org.springframework.expression.ParseException; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; +import static org.junit.Assert.*; + /** * Common superclass for expression tests. * @@ -36,187 +35,146 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; */ public abstract class ExpressionTestCase { - private final static boolean DEBUG = false; + private static final boolean DEBUG = false; + + protected static final boolean SHOULD_BE_WRITABLE = true; + + protected static final boolean SHOULD_NOT_BE_WRITABLE = false; - protected final static boolean SHOULD_BE_WRITABLE = true; - protected final static boolean SHOULD_NOT_BE_WRITABLE = false; protected final ExpressionParser parser = new SpelExpressionParser(); + protected final StandardEvaluationContext eContext = TestScenarioCreator.getTestEvaluationContext(); + /** - * Evaluate an expression and check that the actual result matches the expectedValue and the class of the result - * matches the expectedClassOfResult. - * @param expression The expression to evaluate + * Evaluate an expression and check that the actual result matches the + * expectedValue and the class of the result matches the expectedClassOfResult. + * @param expression the expression to evaluate * @param expectedValue the expected result for evaluating the expression * @param expectedResultType the expected class of the evaluation result */ public void evaluate(String expression, Object expectedValue, Class expectedResultType) { - try { - Expression expr = parser.parseExpression(expression); - if (expr == null) { - fail("Parser returned null for expression"); + Expression expr = parser.parseExpression(expression); + if (expr == null) { + fail("Parser returned null for expression"); + } + if (DEBUG) { + SpelUtilities.printAbstractSyntaxTree(System.out, expr); + } + + Object value = expr.getValue(eContext); + + // Check the return value + if (value == null) { + if (expectedValue == null) { + return; // no point doing other checks } - if (DEBUG) { - SpelUtilities.printAbstractSyntaxTree(System.out, expr); - } - // Class expressionType = expr.getValueType(); - // assertEquals("Type of the expression is not as expected. Should be '"+expectedResultType+"' but is - // '"+expressionType+"'", - // expectedResultType,expressionType); + assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null); + } - Object value = expr.getValue(eContext); + Class resultType = value.getClass(); + assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType + + "' but result was of type '" + resultType + "'", expectedResultType, resultType); - // Check the return value - if (value == null) { - if (expectedValue == null) { - return; // no point doing other checks - } - assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, - null); - } - - Class resultType = value.getClass(); - assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType - + "' but result was of type '" + resultType + "'", expectedResultType, resultType); - // .equals/* isAssignableFrom */(resultType), truers); - - // TODO isAssignableFrom would allow some room for compatibility - // in the above expression... - - if (expectedValue instanceof String) { - assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, - ExpressionTestCase.stringValueOf(value)); - } else { - assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value); - } - } catch (EvaluationException ee) { - ee.printStackTrace(); - fail("Unexpected Exception: " + ee.getMessage()); - } catch (ParseException pe) { - pe.printStackTrace(); - fail("Unexpected Exception: " + pe.getMessage()); + if (expectedValue instanceof String) { + assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, + ExpressionTestCase.stringValueOf(value)); + } + else { + assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value); } } public void evaluateAndAskForReturnType(String expression, Object expectedValue, Class expectedResultType) { - try { - Expression expr = parser.parseExpression(expression); - if (expr == null) { - fail("Parser returned null for expression"); - } - if (DEBUG) { - SpelUtilities.printAbstractSyntaxTree(System.out, expr); - } - // Class expressionType = expr.getValueType(); - // assertEquals("Type of the expression is not as expected. Should be '"+expectedResultType+"' but is - // '"+expressionType+"'", - // expectedResultType,expressionType); - - Object value = expr.getValue(eContext, expectedResultType); - if (value == null) { - if (expectedValue == null) - return; // no point doing other checks - assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, - null); - } - - Class resultType = value.getClass(); - assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType - + "' but result was of type '" + resultType + "'", expectedResultType, resultType); - // .equals/* isAssignableFrom */(resultType), truers); - assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value); - // isAssignableFrom would allow some room for compatibility - // in the above expression... - } catch (EvaluationException ee) { - SpelEvaluationException ex = (SpelEvaluationException) ee; - ex.printStackTrace(); - fail("Unexpected EvaluationException: " + ex.getMessage()); - } catch (ParseException pe) { - fail("Unexpected ParseException: " + pe.getMessage()); + Expression expr = parser.parseExpression(expression); + if (expr == null) { + fail("Parser returned null for expression"); } + if (DEBUG) { + SpelUtilities.printAbstractSyntaxTree(System.out, expr); + } + + Object value = expr.getValue(eContext, expectedResultType); + if (value == null) { + if (expectedValue == null) { + return; // no point doing other checks + } + assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null); + } + + Class resultType = value.getClass(); + assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType + + "' but result was of type '" + resultType + "'", expectedResultType, resultType); + assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value); } /** - * Evaluate an expression and check that the actual result matches the expectedValue and the class of the result - * matches the expectedClassOfResult. This method can also check if the expression is writable (for example, it is a - * variable or property reference). - * - * @param expression The expression to evaluate + * Evaluate an expression and check that the actual result matches the + * expectedValue and the class of the result matches the expectedClassOfResult. + * This method can also check if the expression is writable (for example, + * it is a variable or property reference). + * @param expression the expression to evaluate * @param expectedValue the expected result for evaluating the expression * @param expectedClassOfResult the expected class of the evaluation result * @param shouldBeWritable should the parsed expression be writable? */ - public void evaluate(String expression, Object expectedValue, Class expectedClassOfResult, - boolean shouldBeWritable) { - try { - Expression e = parser.parseExpression(expression); - if (e == null) { - fail("Parser returned null for expression"); + public void evaluate(String expression, Object expectedValue, Class expectedClassOfResult, boolean shouldBeWritable) { + Expression expr = parser.parseExpression(expression); + if (expr == null) { + fail("Parser returned null for expression"); + } + if (DEBUG) { + SpelUtilities.printAbstractSyntaxTree(System.out, expr); + } + Object value = expr.getValue(eContext); + if (value == null) { + if (expectedValue == null) { + return; // no point doing other checks } - if (DEBUG) { - SpelUtilities.printAbstractSyntaxTree(System.out, e); - } - Object value = e.getValue(eContext); - if (value == null) { - if (expectedValue == null) - return; // no point doing other - // checks - assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, - null); - } - Class resultType = value.getClass(); - if (expectedValue instanceof String) { - assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, - ExpressionTestCase.stringValueOf(value)); - } else { - assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value); - } -// assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, -// ExpressionTestCase.stringValueOf(value)); - assertEquals("Type of the result was not as expected. Expected '" + expectedClassOfResult - + "' but result was of type '" + resultType + "'", expectedClassOfResult - .equals/* isAssignableFrom */(resultType), true); - // TODO isAssignableFrom would allow some room for compatibility - // in the above expression... + assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null); + } + Class resultType = value.getClass(); + if (expectedValue instanceof String) { + assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, + ExpressionTestCase.stringValueOf(value)); + } + else { + assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value); + } + assertEquals("Type of the result was not as expected. Expected '" + expectedClassOfResult + + "' but result was of type '" + resultType + "'", expectedClassOfResult.equals(resultType), true); - boolean isWritable = e.isWritable(eContext); - if (isWritable != shouldBeWritable) { - if (shouldBeWritable) - fail("Expected the expression to be writable but it is not"); - else - fail("Expected the expression to be readonly but it is not"); - } - } catch (EvaluationException ee) { - ee.printStackTrace(); - fail("Unexpected Exception: " + ee.getMessage()); - } catch (ParseException pe) { - pe.printStackTrace(); - fail("Unexpected Exception: " + pe.getMessage()); + boolean isWritable = expr.isWritable(eContext); + if (isWritable != shouldBeWritable) { + if (shouldBeWritable) + fail("Expected the expression to be writable but it is not"); + else + fail("Expected the expression to be readonly but it is not"); } } /** - * Evaluate the specified expression and ensure the expected message comes out. The message may have inserts and - * they will be checked if otherProperties is specified. The first entry in otherProperties should always be the - * position. - * @param expression The expression to evaluate - * @param expectedMessage The expected message - * @param otherProperties The expected inserts within the message + * Evaluate the specified expression and ensure the expected message comes out. + * The message may have inserts and they will be checked if otherProperties is specified. + * The first entry in otherProperties should always be the position. + * @param expression the expression to evaluate + * @param expectedMessage the expected message + * @param otherProperties the expected inserts within the message */ protected void evaluateAndCheckError(String expression, SpelMessage expectedMessage, Object... otherProperties) { evaluateAndCheckError(expression, null, expectedMessage, otherProperties); } /** - * Evaluate the specified expression and ensure the expected message comes out. The message may have inserts and - * they will be checked if otherProperties is specified. The first entry in otherProperties should always be the - * position. - * @param expression The expression to evaluate - * @param expectedReturnType Ask the expression return value to be of this type if possible (null indicates don't - * ask for conversion) - * @param expectedMessage The expected message - * @param otherProperties The expected inserts within the message + * Evaluate the specified expression and ensure the expected message comes out. + * The message may have inserts and they will be checked if otherProperties is specified. + * The first entry in otherProperties should always be the position. + * @param expression the expression to evaluate + * @param expectedReturnType ask the expression return value to be of this type if possible + * ({@code null} indicates don't ask for conversion) + * @param expectedMessage the expected message + * @param otherProperties the expected inserts within the message */ protected void evaluateAndCheckError(String expression, Class expectedReturnType, SpelMessage expectedMessage, Object... otherProperties) { @@ -226,18 +184,16 @@ public abstract class ExpressionTestCase { fail("Parser returned null for expression"); } if (expectedReturnType != null) { - @SuppressWarnings("unused") - Object value = expr.getValue(eContext, expectedReturnType); - } else { - @SuppressWarnings("unused") - Object value = expr.getValue(eContext); + expr.getValue(eContext, expectedReturnType); + } + else { + expr.getValue(eContext); } fail("Should have failed with message " + expectedMessage); - } catch (EvaluationException ee) { + } + catch (EvaluationException ee) { SpelEvaluationException ex = (SpelEvaluationException) ee; if (ex.getMessageCode() != expectedMessage) { -// System.out.println(ex.getMessage()); - ex.printStackTrace(); assertEquals("Failed to get expected message", expectedMessage, ex.getMessageCode()); } if (otherProperties != null && otherProperties.length != 0) { @@ -251,66 +207,49 @@ public abstract class ExpressionTestCase { inserts = new Object[0]; } if (inserts.length < otherProperties.length - 1) { - ex.printStackTrace(); - fail("Cannot check " + (otherProperties.length - 1) - + " properties of the exception, it only has " + inserts.length + " inserts"); + fail("Cannot check " + (otherProperties.length - 1) + + " properties of the exception, it only has " + inserts.length + " inserts"); } for (int i = 1; i < otherProperties.length; i++) { if (otherProperties[i] == null) { if (inserts[i - 1] != null) { - ex.printStackTrace(); - fail("Insert does not match, expected 'null' but insert value was '" + inserts[i - 1] - + "'"); + fail("Insert does not match, expected 'null' but insert value was '" + + inserts[i - 1] + "'"); } - } else if (inserts[i - 1] == null) { + } + else if (inserts[i - 1] == null) { if (otherProperties[i] != null) { - ex.printStackTrace(); - fail("Insert does not match, expected '" + otherProperties[i] - + "' but insert value was 'null'"); + fail("Insert does not match, expected '" + otherProperties[i] + + "' but insert value was 'null'"); } - } else if (!inserts[i - 1].equals(otherProperties[i])) { - ex.printStackTrace(); - fail("Insert does not match, expected '" + otherProperties[i] + "' but insert value was '" - + inserts[i - 1] + "'"); + } + else if (!inserts[i - 1].equals(otherProperties[i])) { + fail("Insert does not match, expected '" + otherProperties[i] + + "' but insert value was '" + inserts[i - 1] + "'"); } } } } - } catch (ParseException pe) { - pe.printStackTrace(); - fail("Unexpected Exception: " + pe.getMessage()); } } /** - * Parse the specified expression and ensure the expected message comes out. The message may have inserts and they - * will be checked if otherProperties is specified. The first entry in otherProperties should always be the - * position. - * @param expression The expression to evaluate - * @param expectedMessage The expected message - * @param otherProperties The expected inserts within the message + * Parse the specified expression and ensure the expected message comes out. + * The message may have inserts and they will be checked if otherProperties is specified. + * The first entry in otherProperties should always be the position. + * @param expression the expression to evaluate + * @param expectedMessage the expected message + * @param otherProperties the expected inserts within the message */ protected void parseAndCheckError(String expression, SpelMessage expectedMessage, Object... otherProperties) { try { Expression expr = parser.parseExpression(expression); SpelUtilities.printAbstractSyntaxTree(System.out, expr); fail("Parsing should have failed!"); - } catch (ParseException pe) { -// pe.printStackTrace(); -// Throwable t = pe.getCause(); -// if (t == null) { -// fail("ParseException caught with no defined cause"); -// } -// if (!(t instanceof SpelEvaluationException)) { -// t.printStackTrace(); -// fail("Cause of parse exception is not a SpelException"); -// } -// SpelEvaluationException ex = (SpelEvaluationException) t; -// pe.printStackTrace(); + } + catch (ParseException pe) { SpelParseException ex = (SpelParseException)pe; if (ex.getMessageCode() != expectedMessage) { -// System.out.println(ex.getMessage()); - ex.printStackTrace(); assertEquals("Failed to get expected message", expectedMessage, ex.getMessageCode()); } if (otherProperties != null && otherProperties.length != 0) { @@ -324,15 +263,13 @@ public abstract class ExpressionTestCase { inserts = new Object[0]; } if (inserts.length < otherProperties.length - 1) { - ex.printStackTrace(); - fail("Cannot check " + (otherProperties.length - 1) - + " properties of the exception, it only has " + inserts.length + " inserts"); + fail("Cannot check " + (otherProperties.length - 1) + + " properties of the exception, it only has " + inserts.length + " inserts"); } for (int i = 1; i < otherProperties.length; i++) { if (!inserts[i - 1].equals(otherProperties[i])) { - ex.printStackTrace(); - fail("Insert does not match, expected '" + otherProperties[i] + "' but insert value was '" - + inserts[i - 1] + "'"); + fail("Insert does not match, expected '" + otherProperties[i] + + "' but insert value was '" + inserts[i - 1] + "'"); } } } @@ -340,12 +277,13 @@ public abstract class ExpressionTestCase { } } + public static String stringValueOf(Object value) { return stringValueOf(value, false); } + /** * Produce a nice string representation of the input object. - * * @param value object to be formatted * @return a nice string */ @@ -368,7 +306,8 @@ public abstract class ExpressionTestCase { sb.append(stringValueOf(l[j])); } sb.append("}"); - } else if (primitiveType == Long.TYPE) { + } + else if (primitiveType == Long.TYPE) { long[] l = (long[]) value; sb.append("long[").append(l.length).append("]{"); for (int j = 0; j < l.length; j++) { @@ -378,11 +317,13 @@ public abstract class ExpressionTestCase { sb.append(stringValueOf(l[j])); } sb.append("}"); - } else { - throw new RuntimeException("Please implement support for type " + primitiveType.getName() - + " in ExpressionTestCase.stringValueOf()"); } - } else if (value.getClass().getComponentType().isArray()) { + else { + throw new RuntimeException("Please implement support for type " + primitiveType.getName() + + " in ExpressionTestCase.stringValueOf()"); + } + } + else if (value.getClass().getComponentType().isArray()) { List l = Arrays.asList((Object[]) value); if (!isNested) { sb.append(value.getClass().getComponentType().getName()); @@ -397,7 +338,8 @@ public abstract class ExpressionTestCase { sb.append(stringValueOf(object, true)); } sb.append("}"); - } else { + } + else { List l = Arrays.asList((Object[]) value); if (!isNested) { sb.append(value.getClass().getComponentType().getName()); @@ -414,7 +356,8 @@ public abstract class ExpressionTestCase { sb.append("}"); } return sb.toString(); - } else { + } + else { return value.toString(); } } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/MethodInvocationTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/MethodInvocationTests.java index 682dfe525e..86723e2a16 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/MethodInvocationTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/MethodInvocationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -16,9 +16,6 @@ package org.springframework.expression.spel; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; - import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -26,8 +23,8 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; -import org.junit.Assert; import org.junit.Test; + import org.springframework.core.convert.TypeDescriptor; import org.springframework.expression.AccessException; import org.springframework.expression.BeanResolver; @@ -42,6 +39,8 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.testresources.PlaceOfBirth; +import static org.junit.Assert.*; + /** * Tests invocation of methods. * @@ -55,17 +54,6 @@ public class MethodInvocationTests extends ExpressionTestCase { evaluate("getPlaceOfBirth().getCity()", "SmilJan", String.class); } - // public void testBuiltInProcessors() { - // evaluate("new int[]{1,2,3,4}.count()", 4, Integer.class); - // evaluate("new int[]{4,3,2,1}.sort()[3]", 4, Integer.class); - // evaluate("new int[]{4,3,2,1}.average()", 2, Integer.class); - // evaluate("new int[]{4,3,2,1}.max()", 4, Integer.class); - // evaluate("new int[]{4,3,2,1}.min()", 1, Integer.class); - // evaluate("new int[]{4,3,2,1,2,3}.distinct().count()", 4, Integer.class); - // evaluate("{1,2,3,null}.nonnull().count()", 3, Integer.class); - // evaluate("new int[]{4,3,2,1,2,3}.distinct().count()", 4, Integer.class); - // } - @Test public void testStringClass() { evaluate("new java.lang.String('hello').charAt(2)", 'l', Character.class); @@ -108,59 +96,57 @@ public class MethodInvocationTests extends ExpressionTestCase { // Normal exit StandardEvaluationContext eContext = TestScenarioCreator.getTestEvaluationContext(); - eContext.setVariable("bar",3); + eContext.setVariable("bar", 3); Object o = expr.getValue(eContext); - Assert.assertEquals(o,3); - Assert.assertEquals(1,parser.parseExpression("counter").getValue(eContext)); + assertEquals(o, 3); + assertEquals(1, parser.parseExpression("counter").getValue(eContext)); // Now the expression has cached that throwException(int) is the right thing to call // Let's change 'bar' to be a PlaceOfBirth which indicates the cached reference is // out of date. - eContext.setVariable("bar",new PlaceOfBirth("London")); + eContext.setVariable("bar", new PlaceOfBirth("London")); o = expr.getValue(eContext); - Assert.assertEquals("London", o); + assertEquals("London", o); // That confirms the logic to mark the cached reference stale and retry is working - - // Now let's cause the method to exit via exception and ensure it doesn't cause - // a retry. + // Now let's cause the method to exit via exception and ensure it doesn't cause a retry. // First, switch back to throwException(int) - eContext.setVariable("bar",3); + eContext.setVariable("bar", 3); o = expr.getValue(eContext); - Assert.assertEquals(3, o); - Assert.assertEquals(2,parser.parseExpression("counter").getValue(eContext)); + assertEquals(3, o); + assertEquals(2, parser.parseExpression("counter").getValue(eContext)); // Now cause it to throw an exception: - eContext.setVariable("bar",1); + eContext.setVariable("bar", 1); try { o = expr.getValue(eContext); - Assert.fail(); - } catch (Exception e) { - if (e instanceof SpelEvaluationException) { - e.printStackTrace(); - Assert.fail("Should not be a SpelEvaluationException"); + fail(); + } + catch (Exception ex) { + if (ex instanceof SpelEvaluationException) { + fail("Should not be a SpelEvaluationException: " + ex); } // normal } // If counter is 4 then the method got called twice! - Assert.assertEquals(3,parser.parseExpression("counter").getValue(eContext)); + assertEquals(3, parser.parseExpression("counter").getValue(eContext)); - eContext.setVariable("bar",4); + eContext.setVariable("bar", 4); try { o = expr.getValue(eContext); - Assert.fail(); - } catch (Exception e) { + fail(); + } + catch (Exception ex) { // 4 means it will throw a checked exception - this will be wrapped - if (!(e instanceof ExpressionInvocationTargetException)) { - e.printStackTrace(); - Assert.fail("Should have been wrapped"); + if (!(ex instanceof ExpressionInvocationTargetException)) { + fail("Should have been wrapped: " + ex); } // normal } // If counter is 5 then the method got called twice! - Assert.assertEquals(4,parser.parseExpression("counter").getValue(eContext)); + assertEquals(4, parser.parseExpression("counter").getValue(eContext)); } /** @@ -177,14 +163,14 @@ public class MethodInvocationTests extends ExpressionTestCase { SpelExpressionParser parser = new SpelExpressionParser(); Expression expr = parser.parseExpression("throwException(#bar)"); - eContext.setVariable("bar",2); + eContext.setVariable("bar", 2); try { expr.getValue(eContext); - Assert.fail(); - } catch (Exception e) { - if (e instanceof SpelEvaluationException) { - e.printStackTrace(); - Assert.fail("Should not be a SpelEvaluationException"); + fail(); + } + catch (Exception ex) { + if (ex instanceof SpelEvaluationException) { + fail("Should not be a SpelEvaluationException: " + ex); } // normal } @@ -201,16 +187,16 @@ public class MethodInvocationTests extends ExpressionTestCase { SpelExpressionParser parser = new SpelExpressionParser(); Expression expr = parser.parseExpression("throwException(#bar)"); - eContext.setVariable("bar",4); + eContext.setVariable("bar", 4); try { expr.getValue(eContext); - Assert.fail(); - } catch (ExpressionInvocationTargetException e) { - Throwable t = e.getCause(); - Assert.assertEquals("org.springframework.expression.spel.testresources.Inventor$TestException", t.getClass().getName()); - return; + fail(); + } + catch (ExpressionInvocationTargetException ex) { + Throwable cause = ex.getCause(); + assertEquals("org.springframework.expression.spel.testresources.Inventor$TestException", + cause.getClass().getName()); } - Assert.fail("Should not be a SpelEvaluationException"); } @Test @@ -223,87 +209,34 @@ public class MethodInvocationTests extends ExpressionTestCase { // Filter will be called but not do anything, so first doit() will be invoked SpelExpression expr = (SpelExpression) parser.parseExpression("doit(1)"); - String result = expr.getValue(context,String.class); - Assert.assertEquals("1",result); - Assert.assertTrue(filter.filterCalled); + String result = expr.getValue(context, String.class); + assertEquals("1", result); + assertTrue(filter.filterCalled); // Filter will now remove non @Anno annotated methods filter.removeIfNotAnnotated = true; filter.filterCalled = false; expr = (SpelExpression) parser.parseExpression("doit(1)"); - result = expr.getValue(context,String.class); - Assert.assertEquals("double 1.0",result); - Assert.assertTrue(filter.filterCalled); + result = expr.getValue(context, String.class); + assertEquals("double 1.0", result); + assertTrue(filter.filterCalled); // check not called for other types - filter.filterCalled=false; + filter.filterCalled = false; context.setRootObject(new String("abc")); expr = (SpelExpression) parser.parseExpression("charAt(0)"); - result = expr.getValue(context,String.class); - Assert.assertEquals("a",result); - Assert.assertFalse(filter.filterCalled); + result = expr.getValue(context, String.class); + assertEquals("a", result); + assertFalse(filter.filterCalled); // check de-registration works filter.filterCalled = false; context.registerMethodFilter(TestObject.class,null);//clear filter context.setRootObject(new TestObject()); expr = (SpelExpression) parser.parseExpression("doit(1)"); - result = expr.getValue(context,String.class); - Assert.assertEquals("1",result); - Assert.assertFalse(filter.filterCalled); - } - - // Simple filter - static class LocalFilter implements MethodFilter { - - public boolean removeIfNotAnnotated = false; - - public boolean filterCalled = false; - - private boolean isAnnotated(Method m) { - Annotation[] annos = m.getAnnotations(); - if (annos==null) { - return false; - } - for (Annotation anno: annos) { - String s = anno.annotationType().getName(); - if (s.endsWith("Anno")) { - return true; - } - } - return false; - } - - @Override - public List filter(List methods) { - filterCalled = true; - List forRemoval = new ArrayList(); - for (Method m: methods) { - if (removeIfNotAnnotated && !isAnnotated(m)) { - forRemoval.add(m); - } - } - for (Method m: forRemoval) { - methods.remove(m); - } - return methods; - } - - } - - @Retention(RetentionPolicy.RUNTIME) - @interface Anno {} - - class TestObject { - public int doit(int i) { - return i; - } - - @Anno - public String doit(double d) { - return "double "+d; - } - + result = expr.getValue(context, String.class); + assertEquals("1", result); + assertFalse(filter.filterCalled); } @Test @@ -312,33 +245,22 @@ public class MethodInvocationTests extends ExpressionTestCase { // reflective method accessor is the only one by default List methodResolvers = ctx.getMethodResolvers(); - Assert.assertEquals(1,methodResolvers.size()); + assertEquals(1, methodResolvers.size()); MethodResolver dummy = new DummyMethodResolver(); ctx.addMethodResolver(dummy); - Assert.assertEquals(2,ctx.getMethodResolvers().size()); + assertEquals(2, ctx.getMethodResolvers().size()); List copy = new ArrayList(); copy.addAll(ctx.getMethodResolvers()); - Assert.assertTrue(ctx.removeMethodResolver(dummy)); - Assert.assertFalse(ctx.removeMethodResolver(dummy)); - Assert.assertEquals(1,ctx.getMethodResolvers().size()); + assertTrue(ctx.removeMethodResolver(dummy)); + assertFalse(ctx.removeMethodResolver(dummy)); + assertEquals(1, ctx.getMethodResolvers().size()); ctx.setMethodResolvers(copy); - Assert.assertEquals(2,ctx.getMethodResolvers().size()); + assertEquals(2, ctx.getMethodResolvers().size()); } - static class DummyMethodResolver implements MethodResolver { - - @Override - public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, - List argumentTypes) throws AccessException { - throw new UnsupportedOperationException("Auto-generated method stub"); - } - - } - - @Test public void testVarargsInvocation01() { // Calling 'public int aVarargsMethod(String... strings)' @@ -382,8 +304,7 @@ public class MethodInvocationTests extends ExpressionTestCase { StandardEvaluationContext context = new StandardEvaluationContext(bytes); context.setBeanResolver(new BeanResolver() { @Override - public Object resolve(EvaluationContext context, String beanName) - throws AccessException { + public Object resolve(EvaluationContext context, String beanName) throws AccessException { if ("service".equals(beanName)) { return service; } @@ -395,10 +316,78 @@ public class MethodInvocationTests extends ExpressionTestCase { assertSame(bytes, outBytes); } + + // Simple filter + static class LocalFilter implements MethodFilter { + + public boolean removeIfNotAnnotated = false; + + public boolean filterCalled = false; + + private boolean isAnnotated(Method method) { + Annotation[] anns = method.getAnnotations(); + if (anns == null) { + return false; + } + for (Annotation ann : anns) { + String name = ann.annotationType().getName(); + if (name.endsWith("Anno")) { + return true; + } + } + return false; + } + + @Override + public List filter(List methods) { + filterCalled = true; + List forRemoval = new ArrayList(); + for (Method method: methods) { + if (removeIfNotAnnotated && !isAnnotated(method)) { + forRemoval.add(method); + } + } + for (Method method: forRemoval) { + methods.remove(method); + } + return methods; + } + } + + + @Retention(RetentionPolicy.RUNTIME) + @interface Anno { + } + + + class TestObject { + + public int doit(int i) { + return i; + } + + @Anno + public String doit(double d) { + return "double "+d; + } + } + + + static class DummyMethodResolver implements MethodResolver { + + @Override + public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, + List argumentTypes) throws AccessException { + throw new UnsupportedOperationException(); + } + } + + public static class BytesService { public byte[] handleBytes(byte[] bytes) { return bytes; } } + } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/TestScenarioCreator.java b/spring-expression/src/test/java/org/springframework/expression/spel/TestScenarioCreator.java index 05327188c0..caea1aa457 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/TestScenarioCreator.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/TestScenarioCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2015 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. @@ -22,9 +22,9 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.testresources.Inventor; import org.springframework.expression.spel.testresources.PlaceOfBirth; -///CLOVER:OFF /** - * Builds an evaluation context for test expressions. Features of the test evaluation context are: + * Builds an evaluation context for test expressions. + * Features of the test evaluation context are: *
    *
  • The root context object is an Inventor instance {@link Inventor} *
@@ -45,21 +45,19 @@ public class TestScenarioCreator { */ private static void populateFunctions(StandardEvaluationContext testContext) { try { - testContext.registerFunction("isEven", TestScenarioCreator.class.getDeclaredMethod("isEven", - new Class[] { Integer.TYPE })); - testContext.registerFunction("reverseInt", TestScenarioCreator.class.getDeclaredMethod("reverseInt", - new Class[] { Integer.TYPE, Integer.TYPE, Integer.TYPE })); - testContext.registerFunction("reverseString", TestScenarioCreator.class.getDeclaredMethod("reverseString", - new Class[] { String.class })); - testContext.registerFunction("varargsFunctionReverseStringsAndMerge", TestScenarioCreator.class - .getDeclaredMethod("varargsFunctionReverseStringsAndMerge", new Class[] { String[].class })); - testContext.registerFunction("varargsFunctionReverseStringsAndMerge2", TestScenarioCreator.class - .getDeclaredMethod("varargsFunctionReverseStringsAndMerge2", new Class[] { Integer.TYPE, - String[].class })); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); + testContext.registerFunction("isEven", + TestScenarioCreator.class.getDeclaredMethod("isEven", Integer.TYPE)); + testContext.registerFunction("reverseInt", + TestScenarioCreator.class.getDeclaredMethod("reverseInt", Integer.TYPE, Integer.TYPE, Integer.TYPE)); + testContext.registerFunction("reverseString", + TestScenarioCreator.class.getDeclaredMethod("reverseString", String.class)); + testContext.registerFunction("varargsFunctionReverseStringsAndMerge", + TestScenarioCreator.class.getDeclaredMethod("varargsFunctionReverseStringsAndMerge", String[].class)); + testContext.registerFunction("varargsFunctionReverseStringsAndMerge2", + TestScenarioCreator.class.getDeclaredMethod("varargsFunctionReverseStringsAndMerge2", Integer.TYPE, String[].class)); + } + catch (Exception ex) { + throw new IllegalStateException(ex); } } @@ -72,9 +70,8 @@ public class TestScenarioCreator { } /** - * Create the root context object, an Inventor instance. Non-qualified property and method references will be - * resolved against this context object. - * + * Create the root context object, an Inventor instance. Non-qualified property + * and method references will be resolved against this context object. * @param testContext the evaluation context in which to set the root object */ private static void setupRootContextObject(StandardEvaluationContext testContext) { @@ -88,12 +85,14 @@ public class TestScenarioCreator { testContext.setRootObject(tesla); } + // These methods are registered in the test context and therefore accessible through function calls // in test expressions public static String isEven(int i) { - if ((i % 2) == 0) + if ((i % 2) == 0) { return "y"; + } return "n"; } @@ -129,4 +128,5 @@ public class TestScenarioCreator { } return sb.toString(); } + }