GWT 1.6 MVP and testing, part 1
After successfully building the eventBus, I decided to extend the application to use the MVP (Model-View-Presenter) pattern. The use of this pattern is nicely explained on the google testing blog. Since it’s quite a new way of doing this, there is very little example code available.
Since the gwt best practices are mostly focused on testing, and testing is an invaluable part of application design, we’ll write the test first. I’m not going in detail about Test Driven Development, there are plenty of good books around.
I’ll start with the code straight from the I/O session slides, since that’s what we want.
1. The MockClickEvent, a fake ClickEvent we can send:
public class MockClickEvent extends ClickEvent { }
Easy. And the MockHasClickHandlers class, implementing the minimum required:
class MockHasClickHandlers implements HasClickHandlers { ClickHandler lastClickHandler; public HandlerRegistration addClickHandler(ClickHandler handler) { lastClickHandler = handler; return new HandlerRegistration() { public void removeHandler() { } }; } public void fireEvent(GwtEvent<?> event) { } }
Now we have a fake click event we can send, and a fake class that can be clicked on, aka a fake button. Great.
2. We’re also going to send a String to the table, to fill the added row with. This could be an example of sending values with events.
For this fake string to work, we also need a mock textfield (also only minimum required code):
public class MockHasValue implements HasValue<string> { String lastValue; public String getValue() { return lastValue; } public void setValue(String value) { this.lastValue = value; } public void setValue(String value, boolean fireEvents) { setValue(value); } public HandlerRegistration addValueChangeHandler( ValueChangeHandler<string> handler) { return null; } public void fireEvent(GwtEvent<?> event) { } }
All this we combine in one mock AddRowWidget:
public class MockAddRowWidget implements AddRowWidgetInterface { // the Button MockHasClickHandlers save = new MockHasClickHandlers(); // The Textfield MockHasValue value = new MockHasValue(); public HasClickHandlers getSendButton() { return save; } public HasValue<string> getTextValue() { return value; } }
So what do we have so far?
A mock Composite that contains:
- a mock button on which can be (mock) clicked.
- a mock textfield with a value string.
Next: we need a mock table, implementing the SpecialTable interface (a custom object that has a addRow function), that can listen to the mock event and react accordingly:
public class MockSpecialTableWidget implements SpecialTableInterface { public String rowValue; public void addSpecialRow(String value) { this.rowValue = value; } }
Almost done! All the ingredients are in place, let’s create our test:
public void testAddRow() { // initialize our mock objects MockAddRowWidget mockWidget = new MockAddRowWidget(); MockSpecialTableWidget mockTableWidget = new MockSpecialTableWidget(); create an eventBus HandlerManager eventBus = new HandlerManager(null); // the Presenter class of the listening table binds the (mock) table widget to the eventBus // with a tableRowEventHandler SpecialTablePresenter specialTablePresenter = new SpecialTablePresenter(mockTableWidget, eventBus); // same for the AddRowPresenter: binding (clicking on) the widget to firing the TableRowEvent with the eventBus AddRowPresenter addRowPresenter = new AddRowPresenter(mockWidget, eventBus); // set TextField value mockWidget.value.setValue("testString"); // fake a click on the mock button mockWidget.save.lastClickHandler.onClick(new MockClickEvent()); // Did it pass through? assertTrue(mockWidget.value.getValue() == mockTableWidget.rowValue); }
And result: green bar!

This code is only completely relevant if combined with the MVP code.which will be shown in a next post. Stay tuned!
[...] table) are now completely separated, the timing of the event is no longer imporant. Next Up: – Adding testing. – Adding MVP. – working with GIN. – [...]
Pingback by code » Building a GWT 1.6 application: Managing events with an eventBus — June 26, 2009 @ 3:46 pm
[...] http://www.webspin.be/2009/06/gwt-1-6-mvp-and-testing-part-1/ Possibly related posts: (automatically generated)How to setup Ext js-GWT : GXT and Example on Eclipse Ganymede 3.4 [...]
Pingback by GWT Atchitecture anyone? « TechnoBuzz — August 15, 2009 @ 11:26 pm
Interesting !
I suggest a possible refinement:
change
“public class MockAddRowWidget implements AddRowWidgetInterface”
to
“public class MockAddRowWidget extends Widget implements AddRowWidgetInterface”
and then change
“mockWidget.save.lastClickHandler.onClick(new MockClickEvent());”
to
“mockWidget.fireEvent(new MockClickEvent());”
Comment by Francesco Pasqualini — September 2, 2009 @ 6:37 am
I correct my previous post, here is the possible refinement (remove lastClickHandler and MockClickEvent):
change
<<
class MockHasClickHandlers implements HasClickHandlers {
public HandlerRegistration addClickHandler(ClickHandler handler) {
lastClickHandler = handler;
return new HandlerRegistration() {
public void removeHandler() { }
};
}
public void fireEvent(GwtEvent event) { }
}
>>
to
<>
and change
mockWidget.save.lastClickHandler.onClick(new ClickEvent());
to
mockWidget.save.fireEvent(new ClickEvent());
—
every custom widget extends Widget and so inerits the magical fireEvent method
Comment by Francesco Pasqualini — September 2, 2009 @ 7:15 am
…I try again…
I correct my previous post, here is the possible refinement (remove lastClickHandler and MockClickEvent):
change
—
class MockHasClickHandlers implements HasClickHandlers {
public HandlerRegistration addClickHandler(ClickHandler handler) {
lastClickHandler = handler;
return new HandlerRegistration() {
public void removeHandler() { }
};
}
public void fireEvent(GwtEvent event) { }
}
–
to
–
class MockHasClickHandlers extends Widget implements HasClickHandlers){
public HandlerRegistration addClickHandler(ClickHandler handler) {
return addHandler(handler, ClickEvent.TYPE);
}
}
–
and change
mockWidget.save.lastClickHandler.onClick(new ClickEvent());
to
mockWidget.save.fireEvent(new ClickEvent());
—
every custom widget extends Widget and so inerits the magical fireEvent method
Comment by Francesco Pasqualini — September 2, 2009 @ 7:18 am