Polishing

This commit is contained in:
Sam Brannen 2024-02-11 12:47:54 +01:00
parent 6b67972ec4
commit dc2dbd9700
2 changed files with 30 additions and 16 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,8 @@ import java.text.MessageFormat;
/** /**
* Contains all the messages that can be produced by the Spring Expression Language. * Contains all the messages that can be produced by the Spring Expression Language.
* Each message has a kind (info, warn, error) and a code number. Tests can be written to *
* <p>Each message has a kind (info, warn, error) and a code number. Tests can be written to
* expect particular code numbers rather than particular text, enabling the message text * expect particular code numbers rather than particular text, enabling the message text
* to more easily be modified and the tests to run successfully in different locales. * to more easily be modified and the tests to run successfully in different locales.
* *
@ -100,7 +101,7 @@ public enum SpelMessage {
"A problem occurred whilst attempting to access the property ''{0}'': ''{1}''"), "A problem occurred whilst attempting to access the property ''{0}'': ''{1}''"),
FUNCTION_REFERENCE_CANNOT_BE_INVOKED(Kind.ERROR, 1022, FUNCTION_REFERENCE_CANNOT_BE_INVOKED(Kind.ERROR, 1022,
"The function ''{0}'' mapped to an object of type ''{1}'' which cannot be invoked"), "The function ''{0}'' mapped to an object of type ''{1}'' cannot be invoked"),
EXCEPTION_DURING_FUNCTION_CALL(Kind.ERROR, 1023, EXCEPTION_DURING_FUNCTION_CALL(Kind.ERROR, 1023,
"A problem occurred whilst attempting to invoke the function ''{0}'': ''{1}''"), "A problem occurred whilst attempting to invoke the function ''{0}'': ''{1}''"),

View File

@ -23,9 +23,11 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.expression.spel.SpelMessage.FUNCTION_MUST_BE_STATIC;
import static org.springframework.expression.spel.SpelMessage.INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION;
/** /**
* Tests the evaluation of expressions that access variables and functions (lambda/java). * Tests the evaluation of expressions that access variables and functions.
* *
* @author Andy Clement * @author Andy Clement
* @author Sam Brannen * @author Sam Brannen
@ -33,32 +35,43 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
class VariableAndFunctionTests extends AbstractExpressionTests { class VariableAndFunctionTests extends AbstractExpressionTests {
@Test @Test
void testVariableAccess01() { void variableAccess() {
evaluate("#answer", "42", Integer.class, SHOULD_BE_WRITABLE); evaluate("#answer", "42", Integer.class, SHOULD_BE_WRITABLE);
evaluate("#answer / 2", 21, Integer.class, SHOULD_NOT_BE_WRITABLE); evaluate("#answer / 2", 21, Integer.class, SHOULD_NOT_BE_WRITABLE);
} }
@Test @Test
void testVariableAccess_WellKnownVariables() { void variableAccessWithWellKnownVariables() {
evaluate("#this.getName()","Nikola Tesla",String.class); evaluate("#this.getName()", "Nikola Tesla", String.class);
evaluate("#root.getName()","Nikola Tesla",String.class); evaluate("#root.getName()", "Nikola Tesla", String.class);
} }
@Test @Test
void testFunctionAccess01() { void functionInvocationWithIncorrectNumberOfArguments() {
// Method: reverseInt() expects 3 ints
evaluateAndCheckError("#reverseInt()", INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, 0, 0, 3);
evaluateAndCheckError("#reverseInt(1,2)", INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, 0, 2, 3);
evaluateAndCheckError("#reverseInt(1,2,3,4)", INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, 0, 4, 3);
// MethodHandle: message() maps to java.lang.String.format(String, Object...)
evaluateAndCheckError("#message()", INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, 0, 0, 2);
evaluateAndCheckError("#message('%s')", INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, 0, 1, 2);
}
@Test
void functionInvocationWithPrimitiveArguments() {
evaluate("#reverseInt(1,2,3)", "int[3]{3,2,1}", int[].class); evaluate("#reverseInt(1,2,3)", "int[3]{3,2,1}", int[].class);
evaluate("#reverseInt('1',2,3)", "int[3]{3,2,1}", int[].class); // requires type conversion of '1' to 1 evaluate("#reverseInt('1',2,3)", "int[3]{3,2,1}", int[].class); // requires type conversion of '1' to 1
evaluateAndCheckError("#reverseInt(1)", SpelMessage.INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, 0, 1, 3);
} }
@Test @Test
void testFunctionAccess02() { void functionInvocationWithStringArgument() {
evaluate("#reverseString('hello')", "olleh", String.class); evaluate("#reverseString('hello')", "olleh", String.class);
evaluate("#reverseString(37)", "73", String.class); // requires type conversion of 37 to '37' evaluate("#reverseString(37)", "73", String.class); // requires type conversion of 37 to '37'
} }
@Test @Test
void testCallVarargsFunction() { void functionWithVarargs() {
evaluate("#varargsFunction()", "[]", String.class); evaluate("#varargsFunction()", "[]", String.class);
evaluate("#varargsFunction(new String[0])", "[]", String.class); evaluate("#varargsFunction(new String[0])", "[]", String.class);
evaluate("#varargsFunction('a')", "[a]", String.class); evaluate("#varargsFunction('a')", "[a]", String.class);
@ -89,13 +102,13 @@ class VariableAndFunctionTests extends AbstractExpressionTests {
} }
@Test @Test
void testCallingIllegalFunctions() throws Exception { void functionMethodMustBeStatic() throws Exception {
SpelExpressionParser parser = new SpelExpressionParser(); SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext ctx = new StandardEvaluationContext(); StandardEvaluationContext ctx = new StandardEvaluationContext();
ctx.setVariable("notStatic", this.getClass().getMethod("nonStatic")); ctx.setVariable("notStatic", this.getClass().getMethod("nonStatic"));
assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() -> assertThatExceptionOfType(SpelEvaluationException.class)
parser.parseRaw("#notStatic()").getValue(ctx)). .isThrownBy(() -> parser.parseRaw("#notStatic()").getValue(ctx))
satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(SpelMessage.FUNCTION_MUST_BE_STATIC)); .satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(FUNCTION_MUST_BE_STATIC));
} }