Unit-Test mit EasyMock – Parameter-Check
Kürzlich habe ich ein Bugfix in einer Service-Klasse gemacht, der verhindern sollte, daß ein String länger als 64 Zeichen wird. Da es sich an dieser Stelle um ein Label gehandelte, konnte ich es mittels der Apache-Commons-Klasse StringUtils kürzen. Bei der Gelegenheit wollte ich diesen Aspekt im Unit-Test berücksichtigen. Die Frage die sich jedoch stellte: “Wie komme ich an einem im Service erzeugten Parameter mit dem wiederum ein weiterer Service aufgerufen wird?”
Ausschnitt des zu testenden Services:
public UserAccount storeUserAccount(UserContext userContext, UserAccount userAccount){
Assert.notNull(userContext, "userContext != NULL");
Assert.notNull(userAccount, "userAccount != NULL");
.
.
.
// not accessable from outside
String x = calcInInternalMethod();
x = StringUtils.abbreviate(username, 64);
SpecialOject so = delegatedService
.doSomething(userContext, x);
.
.
.
return userAccount;
}
Ich habe keinen EasyMock-Matcher gefunden der die String-Länge prüft. EasyMock unterstützt mit dem Interface IArgumentMatcher jedoch das man einen eigenen Matcher schreiben kann. Der folgende “Matcher” kann die String-Länge prüfen.
import org.easymock.EasyMock;
import org.easymock.IArgumentMatcher;
/**
* Matcher for max-String-length-check with EasyMock.
*
* @author blog.analysisfreaks.de
*/
public class StringLengthMatcher implements IArgumentMatcher{
private int size;
private int actualLength;
/**
* Private Constructor.
* @param size
*/
private StringLengthMatcher(int size) {
this.size = size;
}
/**
* Matcher that checks the max-length of a {@link String}
* @param size (>0)
* @return
*/
public static String notLongerThan(int size){
EasyMock.reportMatcher(new StringLengthMatcher(size));
return null;
}
/**
* {@inheritDoc}
*/
public void appendTo(StringBuffer buffer) {
buffer.append("notLongerThan(")
.append(size).append(") size exceeded with lenght == ")
.append(this.actualLength).append("!");
}
/**
* {@inheritDoc}
*/
public boolean matches(Object argument) {
if(argument==null) return false;
actualLength = argument.toString().length();
boolean ok = actualLength<=size;
return ok;
}
}
Der Unit-Test sieht dann wie folgt aus:
@Test(description = "test with normal data")
public void testStoreUserAccount() {
.
.
.
EasyMock.expect(delegatedService.doSomething(
(String)EasyMock.anyObject(),
StringLengthMatcher.notLongerThan(64)))
.andReturn(null);
.
.
.
EasyMock.replay(x,y,z,delegatedService);
UserAccount storedUserAccount = benutzerService.storeUserAccount(userContext, userAccount);
EasyMock.verify(x,y,z,delegatedService);
}