Browse Source

Polish ExpressionState[Tests]

pull/31346/head
Sam Brannen 12 months ago
parent
commit
dbf6f7dc9d
  1. 6
      spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java
  2. 111
      spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java

6
spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java

@ -93,6 +93,7 @@ public class ExpressionState { @@ -93,6 +93,7 @@ public class ExpressionState {
public ExpressionState(EvaluationContext context, TypedValue rootObject, SpelParserConfiguration configuration) {
Assert.notNull(context, "EvaluationContext must not be null");
Assert.notNull(context, "'rootObject' must not be null");
Assert.notNull(configuration, "SpelParserConfiguration must not be null");
this.relatedContext = context;
this.rootObject = rootObject;
@ -203,7 +204,7 @@ public class ExpressionState { @@ -203,7 +204,7 @@ public class ExpressionState {
/*
* A new scope is entered when a function is invoked.
*/
public void enterScope(Map<String, Object> argMap) {
public void enterScope(@Nullable Map<String, Object> argMap) {
initVariableScopes().push(new VariableScope(argMap));
initScopeRootObjects().push(getActiveContextObject());
}
@ -300,9 +301,10 @@ public class ExpressionState { @@ -300,9 +301,10 @@ public class ExpressionState {
}
public VariableScope(String name, Object value) {
this.vars.put(name,value);
this.vars.put(name, value);
}
@Nullable
public Object lookupVariable(String name) {
return this.vars.get(name);
}

111
spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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,7 +16,6 @@ @@ -16,7 +16,6 @@
package org.springframework.expression.spel;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
@ -34,27 +33,31 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -34,27 +33,31 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes)
* Tests for {@link ExpressionState}.
*
* <p>Some features are not yet exploited in the language, such as nested scopes
* or local variables scoped to the currently evaluated expression.
*
* <p>Local variables are in variable scopes which come and go during evaluation.
* Normal/global variables are accessible through the {@link EvaluationContext}.
*
* @author Andy Clement
* @author Juergen Hoeller
*/
public class ExpressionStateTests extends AbstractExpressionTests {
class ExpressionStateTests extends AbstractExpressionTests {
private ExpressionState state = new ExpressionState(TestScenarioCreator.getTestEvaluationContext());
@Test
public void testConstruction() {
void construction() {
EvaluationContext context = TestScenarioCreator.getTestEvaluationContext();
ExpressionState state = new ExpressionState(context);
assertThat(state.getEvaluationContext()).isEqualTo(context);
}
// Local variables are in variable scopes which come and go during evaluation. Normal variables are
// accessible through the evaluation context
@Test
public void testLocalVariables() {
ExpressionState state = getState();
void localVariables() {
Object value = state.lookupLocalVariable("foo");
assertThat(value).isNull();
@ -68,8 +71,7 @@ public class ExpressionStateTests extends AbstractExpressionTests { @@ -68,8 +71,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testVariables() {
ExpressionState state = getState();
void globalVariables() {
TypedValue typedValue = state.lookupVariable("foo");
assertThat(typedValue).isEqualTo(TypedValue.NULL);
@ -85,8 +87,7 @@ public class ExpressionStateTests extends AbstractExpressionTests { @@ -85,8 +87,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testNoVariableInterference() {
ExpressionState state = getState();
void noVariableInterference() {
TypedValue typedValue = state.lookupVariable("foo");
assertThat(typedValue).isEqualTo(TypedValue.NULL);
@ -99,8 +100,7 @@ public class ExpressionStateTests extends AbstractExpressionTests { @@ -99,8 +100,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testLocalVariableNestedScopes() {
ExpressionState state = getState();
void localVariableNestedScopes() {
assertThat(state.lookupLocalVariable("foo")).isNull();
state.setLocalVariable("foo",12);
@ -120,30 +120,26 @@ public class ExpressionStateTests extends AbstractExpressionTests { @@ -120,30 +120,26 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testRootContextObject() {
ExpressionState state = getState();
void rootContextObject() {
assertThat(state.getRootContextObject().getValue().getClass()).isEqualTo(Inventor.class);
// although the root object is being set on the evaluation context, the value in the 'state' remains what it was when constructed
// Although the root object is being set on the evaluation context,
// the value in the 'state' remains what it was when constructed.
((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null);
assertThat(state.getRootContextObject().getValue().getClass()).isEqualTo(Inventor.class);
// assertEquals(null, state.getRootContextObject().getValue());
assertThat(state.getRootContextObject().getValue()).isInstanceOf(Inventor.class);
state = new ExpressionState(new StandardEvaluationContext());
assertThat(state.getRootContextObject()).isEqualTo(TypedValue.NULL);
((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null);
assertThat(state.getRootContextObject().getValue()).isNull();
}
@Test
public void testActiveContextObject() {
ExpressionState state = getState();
void activeContextObject() {
assertThat(state.getActiveContextObject().getValue()).isEqualTo(state.getRootContextObject().getValue());
assertThatIllegalStateException().isThrownBy(
state::popActiveContextObject);
assertThatIllegalStateException().isThrownBy(state::popActiveContextObject);
state.pushActiveContextObject(new TypedValue(34));
assertThat(state.getActiveContextObject().getValue()).isEqualTo(34);
@ -162,8 +158,7 @@ public class ExpressionStateTests extends AbstractExpressionTests { @@ -162,8 +158,7 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testPopulatedNestedScopes() {
ExpressionState state = getState();
void populatedNestedScopes() {
assertThat(state.lookupLocalVariable("foo")).isNull();
state.enterScope("foo",34);
@ -181,27 +176,22 @@ public class ExpressionStateTests extends AbstractExpressionTests { @@ -181,27 +176,22 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testRootObjectConstructor() {
EvaluationContext ctx = getContext();
void rootObjectConstructor() {
EvaluationContext ctx = TestScenarioCreator.getTestEvaluationContext();
// TypedValue root = ctx.getRootObject();
// supplied should override root on context
ExpressionState state = new ExpressionState(ctx,new TypedValue("i am a string"));
ExpressionState state = new ExpressionState(ctx, new TypedValue("i am a string"));
TypedValue stateRoot = state.getRootContextObject();
assertThat(stateRoot.getTypeDescriptor().getType()).isEqualTo(String.class);
assertThat(stateRoot.getValue()).isEqualTo("i am a string");
}
@Test
public void testPopulatedNestedScopesMap() {
ExpressionState state = getState();
void populatedNestedScopesMap() {
assertThat(state.lookupLocalVariable("foo")).isNull();
assertThat(state.lookupLocalVariable("goo")).isNull();
Map<String,Object> m = new HashMap<>();
m.put("foo", 34);
m.put("goo", "abc");
state.enterScope(m);
state.enterScope(Map.of("foo", 34, "goo", "abc"));
assertThat(state.lookupLocalVariable("foo")).isEqualTo(34);
assertThat(state.lookupLocalVariable("goo")).isEqualTo("abc");
@ -217,61 +207,42 @@ public class ExpressionStateTests extends AbstractExpressionTests { @@ -217,61 +207,42 @@ public class ExpressionStateTests extends AbstractExpressionTests {
}
@Test
public void testOperators() {
ExpressionState state = getState();
assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() ->
state.operate(Operation.ADD,1,2))
void operators() {
assertThatExceptionOfType(SpelEvaluationException.class)
.isThrownBy(() -> state.operate(Operation.ADD,1,2))
.satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES));
assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() ->
state.operate(Operation.ADD,null,null))
assertThatExceptionOfType(SpelEvaluationException.class)
.isThrownBy(() -> state.operate(Operation.ADD,null,null))
.satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES));
}
@Test
public void testComparator() {
ExpressionState state = getState();
void comparator() {
assertThat(state.getTypeComparator()).isEqualTo(state.getEvaluationContext().getTypeComparator());
}
@Test
public void testTypeLocator() throws EvaluationException {
ExpressionState state = getState();
void typeLocator() throws EvaluationException {
assertThat(state.getEvaluationContext().getTypeLocator()).isNotNull();
assertThat(state.findType("java.lang.Integer")).isEqualTo(Integer.class);
assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() ->
state.findType("someMadeUpName"))
assertThatExceptionOfType(SpelEvaluationException.class)
.isThrownBy(() -> state.findType("someMadeUpName"))
.satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(SpelMessage.TYPE_NOT_FOUND));
}
@Test
public void testTypeConversion() throws EvaluationException {
ExpressionState state = getState();
void typeConversion() throws EvaluationException {
String s = (String) state.convertValue(34, TypeDescriptor.valueOf(String.class));
assertThat(s).isEqualTo("34");
s = (String)state.convertValue(new TypedValue(34), TypeDescriptor.valueOf(String.class));
s = (String) state.convertValue(new TypedValue(34), TypeDescriptor.valueOf(String.class));
assertThat(s).isEqualTo("34");
}
@Test
public void testPropertyAccessors() {
ExpressionState state = getState();
void propertyAccessors() {
assertThat(state.getPropertyAccessors()).isEqualTo(state.getEvaluationContext().getPropertyAccessors());
}
/**
* @return a new ExpressionState
*/
private ExpressionState getState() {
EvaluationContext context = TestScenarioCreator.getTestEvaluationContext();
ExpressionState state = new ExpressionState(context);
return state;
}
private EvaluationContext getContext() {
return TestScenarioCreator.getTestEvaluationContext();
}
}

Loading…
Cancel
Save