Hi,
some of our code uses the GWT History class (specifically the #encodeHistoryToken() method), and while trying to write tests for that code I found that GwtMockito doesn't provide a specific fake for History (fair enough), but unfortunately also that providing one is quite hard: History delegates the encoding to an instance of HistoryImpl, but that one is private, and so the straight-forward way of creating and registering a fake doesn't work.
My work-around for this is to use reflection to make the class accessible enough, and that works reasonably well. But, the work-around is ugly, so I was wondering: is there any specific reason not to make HistoryImpl accessible?
Regards,
--
Andreas
PS: If it helps anyone in the same position, here's the code I'm using. This uses easymock for various reasons, using mockito should work as well:
// Prepare the private HistoryImpl class for mocking
Class<?> historyImplClass = Class.forName("com.google.gwt.user.client.History$HistoryImpl");
Method encodeHistoryTokenMethod = historyImplClass.getMethod("encodeHistoryToken", String.class);
encodeHistoryTokenMethod.setAccessible(true);
// Create the mock itself
Object historyImpl = createNiceMock(historyImplClass);
// Mock #encodeHistoryToken()
encodeHistoryTokenMethod.invoke(historyImpl, isA(String.class));
expectLastCall().andAnswer(new IAnswer<String>() {
@Override
public String answer() throws Throwable {
String value = (String) getCurrentArguments()[0];
if (value == null) {
throw new NullPointerException();
} else if (value.isEmpty()) {
return "";
}
try {
URI uri = new URI(null, null, value);
// URI#getRawFragment() is pretty close, but it does unfortunately retain characters >= U+0080,
// which we do not want.
// Instead, rely on #toASCIIString(), and cut away the '#' in the beginning.
// See also HistoryImpl#encodeHistoryToken()
String encoded = uri.toASCIIString();
assert encoded.charAt(0) == '#' : "Sanity";
return encoded.substring(1).replace("#", "%23");
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Cannot use '" + value + "' as fragment", e);
}
}
}).anyTimes();
replay(historyImpl);
// Finally, tell GwtMockito about it.
GwtMockito.useProviderForType(historyImplClass, new FakeProvider<Object>() {
@Override
public Object getFake(Class<?> type) {
return historyImpl;
}
});