雖然easymock中提供了大量的方法來進(jìn)行參數(shù)匹配,但是對于一些特殊場合比如參數(shù)是復(fù)雜對象而又不能簡單的通過equals()方法來比較,這些現(xiàn)有的參數(shù)匹配器就無能為力了。easymock為此提供了IArgumentMatcher 接口來讓我們實現(xiàn)自定義的參數(shù)匹配器。
我們還是用例子來說話:

public interface Service {
public void execute(Request request);
}
service類的execute()方法接收一個Request實例作為參數(shù), Request是一個javabean:

public static class Request {

private boolean condition;

private String value1;

private String value2;

//ignore getter and setter method
}
假設(shè)在我們的這個單獨的測試案例中,我們有以下參數(shù)匹配邏輯: 如果condition為true,則只需要比較value1;如果condition為false,則只需要比較value2. 由于這個邏輯和默認(rèn)的equals方法不一致,因此我們不能直接使用equals方法,只能實現(xiàn)自己的參數(shù)匹配器。

public class RequestMatcher implements IArgumentMatcher {

private boolean condition;

private String expectedValue;


private RequestMatcher(boolean condition, String expectedValue) {
this.condition = condition;
this.expectedValue = expectedValue;
}

@Override

public void appendTo(StringBuffer buffer) {
buffer.append("RequestMatcher expect(condition=");
buffer.append(condition);
buffer.append(" expectedValue=");
buffer.append(expectedValue);
buffer.append(")");
}

@Override

public boolean matches(Object argument) {

if (!(argument instanceof Request)) {
return false;
}

Request request = (Request) argument;

if (condition) {
return expectedValue.equals(request.getValue1());

} else {
return expectedValue.equals(request.getValue2());
}
}


public static Request requestEquals(boolean condition, String expectedValue) {
EasyMock.reportMatcher(new RequestMatcher(condition, expectedValue));
return null;
}
}
RequestMatcher 是我們定義的參數(shù)匹配器,matches()方法中是參數(shù)匹配邏輯的代碼實現(xiàn),appendTo()方法用于在匹配失敗時打印錯誤信息,后面我們會演示這個方法的使用。然后是最重要的方法requestEquals(),在這里我們通過調(diào)用EasyMock.reportMatcher()告訴easymock我們要用的參數(shù)匹配器。
在測試案例中,我們和以往一樣,先創(chuàng)建了mock對象,然后準(zhǔn)備request對象作為測試數(shù)據(jù)。不同的是,我們沒有使用easymock提供的參數(shù)匹配方法,而是通過service.execute(RequestMatcher.requestEquals(expectedCondition, expectedValue)); 來調(diào)用EasyMock.reportMatcher(),以創(chuàng)建我們自定義的參數(shù)匹配器并為它傳入了兩個必備的參數(shù)expectedCondition和expectedValue。
上面的測試案例可以順利通過,我們的參數(shù)匹配器可以正常工作。然后我們來試試參數(shù)匹配不成功的情況
@Test

public void testConditionTrueFailure() {
final boolean expectedCondition = true;
final String expectedValue = "aaa";

Service service = EasyMock.createMock("service", Service.class);
Request request = prepareRequest(expectedCondition, "bbb", "ccc");
service.execute(RequestMatcher.requestEquals(expectedCondition, expectedValue));
EasyMock.expectLastCall();

EasyMock.replay(service);
service.execute(request);
EasyMock.verify(service);
}
注意在Request request = prepareRequest(expectedCondition, "bbb", "ccc")中,我們故意設(shè)置value為和期望的不同,當(dāng)然這樣測試案例就通不過了,
java.lang.AssertionError:
Unexpected method call service.execute(net.sourcesky.study.easymock.tutorial.IArgumentMatcherTest$Request@10ef90c):
service.execute(RequestMatcher expect(condition=true expectedValue=aaa)): expected: 1, actual: 0
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:45)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:73)
at $Proxy4.execute(Unknown Source)
at net.sourcesky.study.easymock.tutorial.IArgumentMatcherTest.testConditionTrueFailure(IArgumentMatcherTest.java:72)
注意"service.execute(RequestMatcher expect(condition=true expectedValue=aaa)): expected: 1, actual: 0"這行,其中的"RequestMatcher expect(condition=true expectedValue=aaa)"是我們在appendTo()方法中構(gòu)建出來的錯誤信息。appendTo()方法只在這個時候才被調(diào)用,用于生成可讀性強(qiáng)的錯誤信息以便我們在失敗時檢查,因此不要疏忽了這個方法的實現(xiàn)。