There are three groups of scenarios that exist when recording behavior: void methods, non void methods and methods that throw exceptions. Each of which is handled slightly different.
Void Methods
Void methods are the easiest behavior to record. Since they do not return anything, all that is required is to tell the mock object what method is going to be called and with what parameters. This is done by calling the method just as you normally would.
Code Being Tested
…
foo.bar();
String string = “Parameter 2”;
foo.barWithParameters(false, string);
…
Mocking the Behavior
Foo fooMock = EasyMock.createMock(Foo.class);
fooMock.bar();
fooMock.barWithParameters(false, “Parameter 2”);
…
Methods That Return Values
When methods return values a mock object needs to be told the method call and parameters passed as well as what to return. The method EasyMock.expect() is used to tell a mock object to expect a method call.
Code to Be Tested
…
String results = foo.bar();
String string = “Parameter 2”;
BarWithParametersResults bwpr = foo.
barWithParameters(false, string);
…
Mocking the Behavior
…
Foo fooMock = EasyMock.createMock(Foo.class);
EasyMock.expect(foo.bar()).andReturn(“results”);
EasyMock.expect(foo.barWithParameters(false, “Parameter
2”))
.andReturn(new BarWithParametersResults());
…
Methods That Throw Exceptions
Negative testing is an important part of unit testing. In order to be able to test that a method throws the appropriate exceptions when required, a mock object must be able to throw an exception when called.
Methods That Throw Exceptions, Continued
Code to Be Tested
…
try {
String fileName = “C:\tmp\somefile.txt”;
foo.bar(fileName);
} catch (IOException ioe) {
foo.close();
}
…
Mocking the Behavior
…
Foo fooMock = EasyMock.createMock(Foo.class);
EasyMock.expect(fooMock.bar(“C:\tmp\somefile.txt”))
.andThrow(new IOException());
foo.close();
…
Repeated Calls
There are times where a method will be called multiple times or even an unknown number of times. EasyMock provides the ability to indicate those scenarios with the
.times(),
.atleastOnce() and .anyTimes() methods.
…
Foo fooMock = EasyMock.createMock(Foo.class);
EasyMock.expect(foo.bar()).andReturn(“results”).
anyTimes();
EasyMock.expect(foo.barWithParameters(false, “Parameter
2”))
.andReturn(new BarWithParametersResults()).
atLeastOnce();
…
Method |
Description |
.atLeastOnce()
|
Requires that the method call be executed 1 or more times. |
.times(int min,
int max)
|
The number of times the method is called must fall within the specified range (inclusive). |
.anyTimes()
|
Requires that the method be called 0 or more times. |
Table 7. Time methods
Matchers in EasyMock
When replaying recorded behavior in EasyMock, EasyMock uses the .equals() to compare if the passed parameters are what are expected or not. On many objects, this may not be the desired behavior (arrays are one example). EasyMock has a collection of matchers to solve this issue. Matchers are used to compare things in ways other than the .equals() method. Custom matchers can be created by implementing the org.easymock. IArgumentMatcher interface.
Matcher in Action
...
String [] array1 = {“one”, “two”, “three”};
Foo fooMock = EasyMock.createMock(Foo.class);
EasyMock.expect(fooMock.getMiddleElement(
EasyMock.aryEq(array1)).andReturn(“two”);
…
Method |
Description |
eq(Object obj)
|
Accepts a value that is equal to obj |
anyBooelan(),anyByte(),
anyChar(), anyDouble(),
anyFloat(), anyInt(),
anyLong(), anyObject,
anyShort()
|
Accepts any value of the corresponding type. |
eq(float x, float range),
eq(double x, double range)
|
Accepts any value of a float or double within the appropriate ± range. |
aryEq(Array x)
|
Compares the array based on the Array.equals() method. |
isNull()
|
Accepts only null |
notNull()
|
Accepts any object that is not null |
same(Object x)
|
Compares x based on the == method instead of .equals() |
isA(Class clazz)
|
Accepts any object if it is an instance of, descendant of or implements clazz. |
lt(NumericPrimitave x),
leq(NumericPrimitave x),
geq(NumericPrimitave x),
gt(NumericPrimitave x)
|
Accepts a numeric primitive <, <, ≥, > the number provided. |
startsWith(String x),
contains(String x),
endsWith(String x)
|
Accepts any String that starts with, contains or ends with the specified String. x is an actual value not a regular expression. |
and(x, y), or(x, y), not(x)
|
Accepts an object that is either equal to x and y, x or y, or not x respectively |
Table 8. Matcher in action
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}