Running Exemplars isn’t particularly useful if you can’t assert the expected results or behaviour of the method-under-test. This section deals with asserting the expected result, i.e. an expected return value or thrown exception. See the section on Behaviour Verification for details of how to assert the behaviours of the method-under-test.
3.7.1. Expecting a Result Using expect and retval
The expect Exemplar property is used to assert the return value of the annotated method. The expect property can contain one or more SIN Expressions, all of which must return true in order for the Exemplar to pass (otherwise one or more errors are marked against the Exemplar).
Use retval in SIN Expression expect statements to refer to the value returned by the method-under-test in an Exemplar:
@Exemplar(args={"'test'","10","','"}, expect={"=(retval.length(),49)","retval.endsWith('test')"}) public static String repeat(String str, int numTimes, String separator) { StringBuilder retStr = new StringBuilder(); for (int i = 0; i < numTimes; i++) { retStr.append(str); if (i < numTimes - 1) { retStr.append(separator); } } return retStr.toString(); }
3.7.2. Non-Boolean Expects
It is often the case that you will want to compare the return value of the method-under-test with the value or expression given in the Exemplar’s expect property, i.e. =(retval, X) where X is the return value you expect.
For this reason, expect expressions default to this where the Exemplar return value is a non-boolean value. They also default to this if the expression is a boolean literal. For example:
Shorthand expression | Full expression |
5 | =(retval, 5) |
‘testStr’ | =(retval, ‘testStr’) |
true | =(retval, true) |
this.myStr.toUpperCase() | =(retval, this.myStr.toUpperCase()) |
The exception to this is where the expression evaluates to a Class object. In this case the expression defaults to isa(retval, X) rather than =(retval, X). The isa(x,y) built-in method is equivalent to the Java operator instanceof , i.e. isa(x,y) == x instanceof y.
Shorthand expression | Full expression |
List | isa(retval, List) |
MyClass | isa(retval, MyClass) |
com/externalproj/LibClass | isa(retval, com/externalproj/LibClass) |
See the Named Instances section for details of class naming in Sureassert if you are unfamiliar with this.
3.7.3. Expecting Exceptions Using expectexception
You can expect an exception to be thrown using the expectexception Exemplar property. Set this to the simple name of the exception that you expect to be thrown from the method-under-test:
@Exemplar(args={"-1"}, expectexception="IllegalArgumentException") public void deliver(int deliveryFirmID) { if (deliveryFirmID < 0) throw new IllegalArgumentException("deliveryFirmID must be >= 0"); ... }
In addition you can make assertions on the thrown exception using the expects Exemplar property. When an exception is thrown, the Sureassert assigns the exception object to the named instance retval. You can therefore make assertions on the thrown exception in the same way you would make assertions on a method’s return value:
@Exemplar(args={"-1"}, expectexception="IllegalArgumentException", expect="retval.getMessage().contains('deliveryFirmID')") public void deliver(int deliveryFirmID) { if (deliveryFirmID < 0) throw new IllegalArgumentException("deliveryFirmID must be >= 0"); ... }
3.7.4. Making Complex Assertions via External Test Code
You can use the expect property to make assertions on the value returned by the object-under-test, the state of the test instance, or anything else. However there will be times when you need to perform complex assertions by executing code that includes loops and branches to determine if the return value and/or other state is correct.
To accomplish this from your Exemplar, invoke a method within test code from the expect property and pass it the required data. The test method would typically return whether the data is correct via a boolean:
(in production source)
public class Bar { @Exemplar(args={"1"}, expect="FooAsserter.assertDoFoo1(retval, this)") public Foo doFoo1(int param) { ... } }
(in test source)
public class FooAsserter { public static boolean assertDoFoo1(Foo foo, Bar bar) { boolean allOkay = false; // Do some complex analysis of foo and bar return allOkay; } }
3.7.5. Referring to Method Argument Values
Use $argN in SIN Expressions to refer to an argument object or value, where N is the argument number (starting with 1 for the first argument):
@Exemplar(args={"l:'entry1','entry2'","'entry3'"}, expect="=($arg1.size(),3)") public static <E> void addToListNoNull(List<E> list, E obj) { if (obj != null) list.add(obj); }
3.7.6. Setting a Failure Message
You can define a message to be used in the error marker in the event the expect condition fails. To do this, use the notation: ‘my failure message’: expectExpression. For example:
@Exemplar(args={"l:'entry1','entry2'","'entry3'"}, expect="'incorrect size': =($arg1.size(),3)") public static <E> void addToListNoNull(List<E> list, E obj) { if (obj != null) list.add(obj); }