How to mock Listbox when testing the Presenter class?

191 views
Skip to first unread message

BM

unread,
Sep 1, 2011, 12:21:20 PM9/1/11
to Google Web Toolkit
Presenter:
public interface Display {
HasText ageTxtBox();
HasClickHandlers incrementButton();
}

View implements Presenter.Display interface:
@UiField Button incrementButton;
@UiField TextBox ageTxtBox;

@Override
public HasText ageTxtBox() {
return ageTxtBox;
}

@Override
public HasClickHandlers incrementButton() {
return incrementButton;
}

How do we do this for a Listbox in a view?

@UiField ListBox listBoxAdmin;

The methods on listBox I am using are:
addItem
getItemCount
getSelectedIndex
getItemText
getValue
removeItem
clear


How can I test my listbox functionality which is in Presenter with a
mock Listbox? What interface it need to implement?

BM

unread,
Sep 1, 2011, 12:21:20 PM9/1/11
to Google Web Toolkit

Thomas Broyer

unread,
Sep 1, 2011, 12:40:11 PM9/1/11
to google-we...@googlegroups.com
I'd highly encourage you to use the pattern from the "MVP - part 2" article from the GWT doc, where the presenter itself implements an interface that the view calls back, rather than exposing the view through HasXxxHandlers and the like. It makes mocking so much painful! (having to mock HasXxxHandlers is a PITA compared to simply mocking your View interface, and capturing the presenter from the setPresenter method so you can call methods on it as if the view did it).

To answer your question, your view should expose the methods you use from the ListBox (and simply delegate them to the listbox); you shouldn't try to expose "the listbox" as an object from your view (because as you said, there's no "matching" interface). So you'll add those 7 methods to your view (possibly using a naming scheme such as getAdmin, setAdmin, etc.).
Also, instead of a ListBox, you could use a ValueListBox so you can directly "push" your "model" to your view, and get the selected object back from the view.

BM

unread,
Sep 1, 2011, 1:45:05 PM9/1/11
to Google Web Toolkit, bhushan. madan
My ListBox is inside a custom composite widget I have created. I am
using this widget in my different views in my application.

Just to elaborate more on this widget which I created, it is a Dialog
Box which has Left ListBox and Right ListBox. There are 4 buttons on
the center which allows to move items from Left to Right or Right to
Left. They can be moved one at a time or all at once. So when I
created this ListBox using GWT Designer as a New-Windows Builder-
UIBinder - DialogBox I don't get any presenter or activity with that.
Plus I don't want an activity simply because I don't want a new place.
I am opening this custom dialog box within my same place and I don't
want to write the processing code of moving items from either side
inside my current activity because then If my two different views want
to use this custom dialog box I have to duplicate the code. The whole
idea of this Widget was to have self-contained code.
The problem I see with GWT designer is all the event handling code
goes inside UIHandler method which is still inside my
CustomWidget.java file.

How do I then test my widget not inside GWTTestcase?

I introduced a presenter to use classic MVP approach and move my
processing logic inside presenter that way I can test my presenter my
mocking GWT widgets as my own custom widgets.

MVP-Part 2 deals with Activities and Places which works fine when you
are using GWT widgets inside a View. But when you have a re-usable
widget you created I don't want to assign new place and activity for
every custom widget I create. Because I really want to test my widget
and not the view here. See the difference here?

Unless I am missing something here..

BM

unread,
Sep 1, 2011, 2:22:06 PM9/1/11
to Google Web Toolkit
I think I got it what you saying. I got caught up with MVP-Part 2 in
terms of activities and places and kind of lost the major
understanding of what it is ultimately trying to tell you to avoid
HasXxxHandlers.

So I have one question here.. If my presenter implements the interface
which view calls back and how does presenter will get hold of my
listbox defined in the view?

On Sep 1, 11:40 am, Thomas Broyer <t.bro...@gmail.com> wrote:

Thomas Broyer

unread,
Sep 1, 2011, 2:41:58 PM9/1/11
to google-we...@googlegroups.com
It won't; it only talks to the view through the Display interface (or possibly if it's really complex, through sub-objects, but try as hard as possible to keep them seen as interfaces or mockable objects –i.e. objects that you can extend to remove all JSNI dependency– or you'll need a, sluggish, GWTTestCase).

(to quickly answer your previous message, which I didn't read 'til the end, it doesn't really matter how your view is implemented, what matters is how your presenter talks to it, the granularity of the "protocol"/contract impacting how much code you can unit-test without a GWTTestCase: the more code in the presenter, the more code can be tested without GWTTestCase, but also the more complex the presenter, which makes it less readable and maintainable)

BM

unread,
Sep 2, 2011, 11:14:06 AM9/2/11
to Google Web Toolkit
"I'd highly encourage you to use the pattern from the "MVP - part 2"
article
from the GWT doc, where the presenter itself implements an interface
that
the view calls back, rather than exposing the view through
HasXxxHandlers
and the like."

==> Can you elaborate more on this? My only question here is if my
presenter implements the interface and view has the method call
setPresenter which basically binds that presenter to the View, how
does the view calls back those methods implemented in the Presenter?
Does view need to pass every UIField in the method call to Presenter?
That is where I am lost here. Sorry I am new to GWT but I want to be
perfect so asking lot of questions.



On Sep 1, 11:40 am, Thomas Broyer <t.bro...@gmail.com> wrote:

Thomas Broyer

unread,
Sep 2, 2011, 12:02:40 PM9/2/11
to google-we...@googlegroups.com
I'm sorry I don't understand; the code from the article (and the "Activities and Places" page from the documentation) speaks for itself.

interface Presenter: defines methods called by the view (generally in response to user events)
interface View: defines methods called by the presenter to update the view + defines a setPresenter(Presenter) method.

class MyPresenter: implements the Presenter interface, receives a View in its constructor. At one point, calls the view.setPresenter(this) (if MyPresenter is an activity, you'd probably do that in the start() method; and I like calling view.setPresenter(null) in onStop and onCancel so it "cleans things up after itself")
class MyView: implements the View interface. When it needs to talk to the presenter, it uses the one previously set by a call to setPresenter.

MyPresenter doesn't know MyView, only View; and MyView doesn't know MyPresenter, only Presenter. But MyPresenter and MyView both have a reference to the other (through the View and Presenter interfaces; the View received in the Presenter's constructor, and the Presenter receivedin the View's setPresenter)

When you test MyPresenter, you mock View, and call methods from the implemented Presenter interface to simulate user actions on the view.

(note: this is how many people do; if you prefer injecting the presenter into the view, injecting it with a setter rather than the constructor, etc. feel free to do it the way you like it, the way feel comfortable with)

BM

unread,
Sep 2, 2011, 1:58:59 PM9/2/11
to Google Web Toolkit
Hi Thomas,
AHHA !! Thank you very much!! Finally I understood it!! I owe you
one.

I think I was getting confused with the term "activity". You helped me
clear the doubt that my presenter can act itself as a presenter or
presenter + activity together.

Now I understood what you meant by "mock HasXxxHandlers" and why it is
so painful.

Seriously thanks a bunch! I appreciate it and that's what I love about
this community.

Gael Lazzari

unread,
Sep 13, 2011, 2:14:57 PM9/13/11
to google-we...@googlegroups.com
Did you have a look to the gwt-test-utils framework ? (http://code.google.com/p/gwt-test-utils/)

It enables you to launch GWT client side code in a standard JUnit test, without GWTTestCase. It's way faster than GWTTestCase and doesn't expect you to mock every HasXXX widgets since they are really instanciated. 

Also, it enables you to write more complete test in java, not only tests that stick with your Presenters : it enables you to test your bindings and can even simulate any web browser event (click, blur, change...)
Reply all
Reply to author
Forward
0 new messages