Tuesday, February 17, 2015

GWT 2.7/GwtMockito: History support

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;
   
}
});



--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment