More tests. First pass on messages review.

This commit is contained in:
Andy Clement
2009-04-12 16:45:00 +00:00
parent f6ecffdba7
commit af6457a67d
12 changed files with 310 additions and 175 deletions

View File

@@ -94,7 +94,7 @@ public class EvaluationTests extends ExpressionTestCase {
public void testPropertyField01() {
evaluate("name", "Nikola Tesla", String.class, false);
// not writable because (1) name is private (2) there is no setter, only a getter
evaluateAndCheckError("madeup", SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, 0, "madeup",
evaluateAndCheckError("madeup", SpelMessages.PROPERTY_OR_FIELD_NOT_READABLE, 0, "madeup",
"org.springframework.expression.spel.testresources.Inventor");
}

View File

@@ -203,9 +203,8 @@ public class ExpressionLanguageScenarioTests extends ExpressionTestCase {
try {
expr.setValue(ctx, Color.blue);
fail("Should not be allowed to set oranges to be blue !");
}
catch (SpelException ee) {
assertEquals(ee.getMessageUnformatted(), SpelMessages.PROPERTY_OR_FIELD_SETTER_NOT_FOUND);
} catch (SpelException ee) {
assertEquals(ee.getMessageUnformatted(), SpelMessages.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL);
}
}
@@ -225,7 +224,7 @@ public class ExpressionLanguageScenarioTests extends ExpressionTestCase {
fail("Should not be allowed to set peas to be blue !");
}
catch (SpelException ee) {
assertEquals(ee.getMessageUnformatted(), SpelMessages.PROPERTY_OR_FIELD_SETTER_NOT_FOUND);
assertEquals(ee.getMessageUnformatted(), SpelMessages.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL);
}
}

View File

@@ -17,9 +17,15 @@ package org.springframework.expression.spel;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import org.springframework.expression.ParseException;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.ast.FormatHelper;
import org.springframework.expression.spel.support.ReflectionHelper;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.expression.spel.support.ReflectionHelper.ArgsMatchKind;
/**
* Tests for any helper code.
@@ -71,4 +77,100 @@ public class HelperTests extends ExpressionTestCase {
assertTrue(s.indexOf("===> Expression '3+4+5+6+7-2' - AST start")!=-1);
assertTrue(s.indexOf(" OperatorPlus value:((((3 + 4) + 5) + 6) + 7) #children:2")!=-1);
}
public void testTypedValue() {
TypedValue tValue = new TypedValue("hello");
assertEquals(String.class,tValue.getTypeDescriptor().getType());
assertEquals("TypedValue: hello of type java.lang.String",tValue.toString());
}
public void testReflectionHelperCompareArguments_ExactMatching() {
StandardTypeConverter typeConverter = new StandardTypeConverter();
// Calling foo(String) with (String) is exact match
checkMatch(new Class[]{String.class},new Class[]{String.class},typeConverter,ArgsMatchKind.EXACT);
// Calling foo(String,Integer) with (String,Integer) is exact match
checkMatch(new Class[]{String.class,Integer.class},new Class[]{String.class,Integer.class},typeConverter,ArgsMatchKind.EXACT);
}
public void testReflectionHelperCompareArguments_Varargs_ExactMatching() {
StandardTypeConverter tc = new StandardTypeConverter();
// Calling foo(String) with (String) is exact match
checkMatch(new Class[]{String.class},new Class[]{String.class},tc,ArgsMatchKind.EXACT);
}
public void testReflectionHelperCompareArguments_CloseMatching() {
StandardTypeConverter typeConverter = new StandardTypeConverter();
// Calling foo(List) with (ArrayList) is close match (no conversion required)
checkMatch(new Class[]{ArrayList.class},new Class[]{List.class},typeConverter,ArgsMatchKind.CLOSE);
// Passing (Sub,String) on call to foo(Super,String) is close match
checkMatch(new Class[]{Sub.class,String.class},new Class[]{Super.class,String.class},typeConverter,ArgsMatchKind.CLOSE);
// Passing (String,Sub) on call to foo(String,Super) is close match
checkMatch(new Class[]{String.class,Sub.class},new Class[]{String.class,Super.class},typeConverter,ArgsMatchKind.CLOSE);
}
public void testReflectionHelperCompareArguments_RequiresConversionMatching() {
StandardTypeConverter typeConverter = new StandardTypeConverter();
// Calling foo(String,int) with (String,Integer) requires boxing conversion of argument one
checkMatch(new Class[]{String.class,Integer.TYPE},new Class[]{String.class,Integer.class},typeConverter,ArgsMatchKind.REQUIRES_CONVERSION,1);
// Passing (int,String) on call to foo(Integer,String) requires boxing conversion of argument zero
checkMatch(new Class[]{Integer.TYPE,String.class},new Class[]{Integer.class, String.class},typeConverter,ArgsMatchKind.REQUIRES_CONVERSION,0);
// Passing (int,Sub) on call to foo(Integer,Super) requires boxing conversion of argument zero
checkMatch(new Class[]{Integer.TYPE,Sub.class},new Class[]{Integer.class, Super.class},typeConverter,ArgsMatchKind.REQUIRES_CONVERSION,0);
// Passing (int,Sub,boolean) on call to foo(Integer,Super,Boolean) requires boxing conversion of arguments zero and two
checkMatch(new Class[]{Integer.TYPE,Sub.class,Boolean.TYPE},new Class[]{Integer.class, Super.class,Boolean.class},typeConverter,ArgsMatchKind.REQUIRES_CONVERSION,0,2);
}
public void testReflectionHelperCompareArguments_NotAMatch() {
StandardTypeConverter typeConverter = new StandardTypeConverter();
// Passing (Super,String) on call to foo(Sub,String) is not a match
checkMatch(new Class[]{Super.class,String.class},new Class[]{Sub.class,String.class},typeConverter,null);
}
static class Super {
}
static class Sub extends Super {
}
// ---
/**
* Used to validate the match returned from a compareArguments call.
*/
private void checkMatch(Class[] inputTypes, Class[] expectedTypes, StandardTypeConverter typeConverter,ArgsMatchKind expectedMatchKind,int... argsForConversion) {
ReflectionHelper.ArgumentsMatchInfo matchInfo = ReflectionHelper.compareArguments(expectedTypes, inputTypes, typeConverter);
if (expectedMatchKind==null) {
assertNull("Did not expect them to match in any way", matchInfo);
} else {
assertNotNull("Should not be a null match", matchInfo);
}
if (expectedMatchKind==ArgsMatchKind.EXACT) {
assertTrue(matchInfo.isExactMatch());
assertNull(matchInfo.argsRequiringConversion);
} else if (expectedMatchKind==ArgsMatchKind.CLOSE) {
assertTrue(matchInfo.isCloseMatch());
assertNull(matchInfo.argsRequiringConversion);
} else if (expectedMatchKind==ArgsMatchKind.REQUIRES_CONVERSION) {
assertTrue("expected to be a match requiring conversion, but was "+matchInfo,matchInfo.isMatchRequiringConversion());
if (argsForConversion==null) {
fail("there are arguments that need conversion");
}
assertEquals("The array of args that need conversion is different length to that expected",argsForConversion.length, matchInfo.argsRequiringConversion.length);
for (int a=0;a<argsForConversion.length;a++) {
assertEquals(argsForConversion[a],matchInfo.argsRequiringConversion[a]);
}
}
}
}

View File

@@ -87,7 +87,7 @@ public class MethodInvocationTests extends ExpressionTestCase {
}
public void testInvocationOnNullContextObject() {
evaluateAndCheckError("null.toString()",SpelMessages.ATTEMPTED_METHOD_CALL_ON_NULL_CONTEXT_OBJECT);
evaluateAndCheckError("null.toString()",SpelMessages.METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED);
}
}

View File

@@ -47,10 +47,41 @@ public class PropertyAccessTests extends ExpressionTestCase {
public void testNonExistentPropertiesAndMethods() {
// madeup does not exist as a property
evaluateAndCheckError("madeup", SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, 0);
evaluateAndCheckError("madeup", SpelMessages.PROPERTY_OR_FIELD_NOT_READABLE, 0);
// name is ok but foobar does not exist:
evaluateAndCheckError("name.foobar", SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, 5);
evaluateAndCheckError("name.foobar", SpelMessages.PROPERTY_OR_FIELD_NOT_READABLE, 5);
}
/**
* The standard reflection resolver cannot find properties on null objects but some
* supplied resolver might be able to - so null shouldn't crash the reflection resolver.
*/
public void testAccessingOnNullObject() throws Exception {
SpelExpression expr = (SpelExpression)parser.parseExpression("madeup");
EvaluationContext context = new StandardEvaluationContext(null);
try {
expr.getValue(context);
fail("Should have failed - default property resolver cannot resolve on null");
} catch (Exception e) {
checkException(e,SpelMessages.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL);
}
assertFalse(expr.isWritable(context));
try {
expr.setValue(context,"abc");
fail("Should have failed - default property resolver cannot resolve on null");
} catch (Exception e) {
checkException(e,SpelMessages.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL);
}
}
private void checkException(Exception e, SpelMessages expectedMessage) {
if (e instanceof SpelException) {
SpelMessages sm = ((SpelException)e).getMessageUnformatted();
assertEquals("Expected exception type did not occur",expectedMessage,sm);
} else {
fail("Should be a SpelException "+e);
}
}
// Adding a new property accessor just for a particular type