Organize and clean up SpEL documentation tests

This commit is contained in:
Sam Brannen 2024-02-01 16:22:14 +01:00
parent a82108ec73
commit 17ee82e004
3 changed files with 528 additions and 541 deletions

View File

@ -40,11 +40,7 @@ Java::
public abstract class StringUtils {
public static String reverseString(String input) {
StringBuilder backwards = new StringBuilder(input.length());
for (int i = 0; i < input.length(); i++) {
backwards.append(input.charAt(input.length() - 1 - i));
}
return backwards.toString();
return new StringBuilder(input).reverse().toString();
}
}
----
@ -54,11 +50,7 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
fun reverseString(input: String): String {
val backwards = StringBuilder(input.length)
for (i in 0 until input.length) {
backwards.append(input[input.length - 1 - i])
}
return backwards.toString()
return StringBuilder(input).reverse().toString()
}
----
======
@ -161,9 +153,9 @@ Java::
.bindTo(varargs); //here we have to provide arguments in a single array binding
context.setVariable("message", mh);
// evaluates to "This is a prerecorded message with 3 words: <Oh Hello World!>"
String message = parser.parseExpression("#message()")
.getValue(context, String.class);
//returns "This is a prerecorded message with 3 words: <Oh Hello World!>"
----
Kotlin::
@ -182,6 +174,7 @@ Kotlin::
.bindTo(varargs) //here we have to provide arguments in a single array binding
context.setVariable("message", mh)
// evaluates to "This is a prerecorded message with 3 words: <Oh Hello World!>"
val message = parser.parseExpression("#message()")
.getValue(context, String::class.java)
----

View File

@ -1,5 +1,5 @@
[[expressions-templating]]
= Expression templating
= Expression Templating
Expression templates allow mixing literal text with one or more evaluation blocks.
Each evaluation block is delimited with prefix and suffix characters that you can
@ -32,53 +32,13 @@ Kotlin::
======
The string is evaluated by concatenating the literal text `'random number is '` with the
result of evaluating the expression inside the `#{ }` delimiter (in this case, the result
of calling that `random()` method). The second argument to the `parseExpression()` method
is of the type `ParserContext`. The `ParserContext` interface is used to influence how
the expression is parsed in order to support the expression templating functionality.
The definition of `TemplateParserContext` follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class TemplateParserContext implements ParserContext {
public String getExpressionPrefix() {
return "#{";
}
public String getExpressionSuffix() {
return "}";
}
public boolean isTemplate() {
return true;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class TemplateParserContext : ParserContext {
override fun getExpressionPrefix(): String {
return "#{"
}
override fun getExpressionSuffix(): String {
return "}"
}
override fun isTemplate(): Boolean {
return true
}
}
----
======
result of evaluating the expression inside the `#{ }` delimiters (in this case, the
result of calling that `random()` method). The second argument to the `parseExpression()`
method is of the type `ParserContext`. The `ParserContext` interface is used to influence
how the expression is parsed in order to support the expression templating functionality.
The `TemplateParserContext` used in the previous example resides in the
`org.springframework.expression.common` package and is an implementation of the
`ParserContext` which by default configures the prefix and suffix to `#{` and `}`,
respectively.

View File

@ -26,12 +26,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@ -53,9 +54,9 @@ import static org.assertj.core.api.Assertions.within;
@SuppressWarnings("rawtypes")
class SpelDocumentationTests extends AbstractExpressionTests {
static Inventor tesla;
private static final Inventor tesla;
static Inventor pupin;
private static final Inventor pupin;
static {
GregorianCalendar c = new GregorianCalendar();
@ -71,6 +72,9 @@ class SpelDocumentationTests extends AbstractExpressionTests {
}
@Nested
class Miscellaneous {
@Test
void methodInvocation() {
evaluate("'Hello World'.concat('!')", "Hello World!", String.class);
@ -115,15 +119,20 @@ class SpelDocumentationTests extends AbstractExpressionTests {
boolean isEqual = exp.getValue(context, Boolean.class); // evaluates to true
assertThat(isEqual).isTrue();
}
}
// Section 7.4.1
@Nested
class ExpressionsInBeanDefinitions {
@Test
void xmlBasedConfig() {
evaluate("(T(java.lang.Math).random() * 100.0 )>0",true,Boolean.class);
}
}
@Nested
class LiteralExpressions {
// Section 7.5
@Test
void literals() {
ExpressionParser parser = new SpelExpressionParser();
@ -143,6 +152,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
Object nullValue = parser.parseExpression("null").getValue();
assertThat(nullValue).isNull();
}
}
@Nested
class PropertiesArraysListsMapsAndIndexers {
@Test
void propertyAccess() {
@ -183,10 +196,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
}
@Test
void dictionaryAccess() {
void maps() {
StandardEvaluationContext societyContext = new StandardEvaluationContext();
societyContext.setRootObject(new IEEE());
// Officer's Dictionary
// Officer's map
Inventor pupin = parser.parseExpression("officers['president']").getValue(societyContext, Inventor.class);
assertThat(pupin).isNotNull();
@ -203,9 +216,13 @@ class SpelDocumentationTests extends AbstractExpressionTests {
Inventor i2 = parser.parseExpression("reverse[0]['advisors'][0]").getValue(societyContext,Inventor.class);
assertThat(i2.getName()).isEqualTo("Nikola Tesla");
}
}
@Nested
class Methods {
@Test
void methodInvocation2() {
void methodInvocation() {
// string literal, evaluates to "bc"
String c = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);
assertThat(c).isEqualTo("bc");
@ -216,9 +233,13 @@ class SpelDocumentationTests extends AbstractExpressionTests {
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);
assertThat(isMember).isTrue();
}
}
@Nested
class Operators {
@Test
void relationalOperators() {
void standardRelationalOperators() {
boolean result = parser.parseExpression("2 == 2").getValue(Boolean.class);
assertThat(result).isTrue();
@ -232,7 +253,7 @@ class SpelDocumentationTests extends AbstractExpressionTests {
}
@Test
void otherOperators() {
void otherRelationalOperators() {
boolean result;
// evaluates to true
@ -426,6 +447,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
assertThat(parser.parseExpression("foo").getValue(context, inventor, String.class)).isEqualTo("Alexandar Seovic");
assertThat(aleks).isEqualTo("Alexandar Seovic");
}
}
@Nested
class Types {
@Test
void types() {
@ -434,6 +459,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);
assertThat(trueValue).isTrue();
}
}
@Nested
class Constructors {
@Test
void constructors() {
@ -445,6 +474,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
//create new inventor instance within add method of List
parser.parseExpression("Members2.add(new org.springframework.expression.spel.testresources.Inventor('Albert Einstein', 'German'))").getValue(societyContext);
}
}
@Nested
class Variables {
@Test
void variables() {
@ -504,6 +537,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
"Nikola Tesla invented the Telephone repeater.",
"Nikola Tesla invented the Tesla coil transformer.");
}
}
@Nested
class Functions {
@Test
void functions() throws Exception {
@ -516,7 +553,7 @@ class SpelDocumentationTests extends AbstractExpressionTests {
}
@Test
void methodHandlesNotBound() throws Throwable {
void methodHandlesNotBound() throws Exception {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
@ -546,6 +583,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
.getValue(context, String.class);
assertThat(message).isEqualTo("This is a prerecorded message with 3 words: <Oh Hello World!>");
}
}
@Nested
class TernaryOperator {
@Test
void ternary() {
@ -566,6 +607,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
assertThat(queryResultString).isEqualTo("Nikola Tesla is a member of the IEEE Society");
// queryResultString = "Nikola Tesla is a member of the IEEE Society"
}
}
@Nested
class CollectionSelection {
@Test
@SuppressWarnings("unchecked")
@ -576,31 +621,20 @@ class SpelDocumentationTests extends AbstractExpressionTests {
assertThat(list).hasSize(1);
assertThat(list.get(0).getName()).isEqualTo("Nikola Tesla");
}
}
@Nested
class ExpressionTemplating {
@Test
void templating() {
String randomPhrase =
parser.parseExpression("random number is ${T(java.lang.Math).random()}", new TemplatedParserContext()).getValue(String.class);
parser.parseExpression("random number is ${T(java.lang.Math).random()}",
new TemplateParserContext()).getValue(String.class);
assertThat(randomPhrase).startsWith("random number");
}
static class TemplatedParserContext implements ParserContext {
@Override
public String getExpressionPrefix() {
return "${";
}
@Override
public String getExpressionSuffix() {
return "}";
}
@Override
public boolean isTemplate() {
return true;
}
}
static class IEEE {
private String name;