From dbf6f7dc9d363b28c9a3e5f931c36db2be97ca35 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sat, 30 Sep 2023 11:45:20 +0200 Subject: [PATCH] Polish ExpressionState[Tests] --- .../expression/spel/ExpressionState.java | 6 +- .../expression/spel/ExpressionStateTests.java | 111 +++++++----------- 2 files changed, 45 insertions(+), 72 deletions(-) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java b/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java index 8dadae596732..890fc10453f3 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ExpressionState.java @@ -93,6 +93,7 @@ public ExpressionState(EvaluationContext context, TypedValue rootObject) { 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 Object convertValue(TypedValue value, TypeDescriptor targetTypeDescriptor /* * A new scope is entered when a function is invoked. */ - public void enterScope(Map argMap) { + public void enterScope(@Nullable Map argMap) { initVariableScopes().push(new VariableScope(argMap)); initScopeRootObjects().push(getActiveContextObject()); } @@ -300,9 +301,10 @@ public VariableScope(@Nullable Map arguments) { } 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); } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java index bb318afa1f1d..999c1c537ad5 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/ExpressionStateTests.java @@ -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 @@ 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.assertThatIllegalStateException; /** - * Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes) + * Tests for {@link ExpressionState}. + * + *

Some features are not yet exploited in the language, such as nested scopes + * or local variables scoped to the currently evaluated expression. + * + *

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 void testLocalVariables() { } @Test - public void testVariables() { - ExpressionState state = getState(); + void globalVariables() { TypedValue typedValue = state.lookupVariable("foo"); assertThat(typedValue).isEqualTo(TypedValue.NULL); @@ -85,8 +87,7 @@ public void testVariables() { } @Test - public void testNoVariableInterference() { - ExpressionState state = getState(); + void noVariableInterference() { TypedValue typedValue = state.lookupVariable("foo"); assertThat(typedValue).isEqualTo(TypedValue.NULL); @@ -99,8 +100,7 @@ public void testNoVariableInterference() { } @Test - public void testLocalVariableNestedScopes() { - ExpressionState state = getState(); + void localVariableNestedScopes() { assertThat(state.lookupLocalVariable("foo")).isNull(); state.setLocalVariable("foo",12); @@ -120,30 +120,26 @@ public void testLocalVariableNestedScopes() { } @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 void testActiveContextObject() { } @Test - public void testPopulatedNestedScopes() { - ExpressionState state = getState(); + void populatedNestedScopes() { assertThat(state.lookupLocalVariable("foo")).isNull(); state.enterScope("foo",34); @@ -181,27 +176,22 @@ public void testPopulatedNestedScopes() { } @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 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 void testPopulatedNestedScopesMap() { } @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(); - } - }