Presenter unit testing: mocking and injecting HttpServletRequest

522 views
Skip to first unread message

dindeman

unread,
Apr 23, 2011, 12:40:15 PM4/23/11
to GWTP
Hi everyone, Philippe, Christian.

Just wanted to share something I just did in the context of unit
testing.
I was following the instructions on the wiki page
http://code.google.com/p/gwt-platform/wiki/UnitTesting in order to
unit test one of my presenters. And I came across an error when
running the test:

com.google.inject.CreationException: Guice creation errors:

1) No implementation for javax.servlet.http.HttpServletRequest was
bound.
while locating
com.google.inject.Provider<javax.servlet.http.HttpServletRequest>
for parameter 0 at
com.gwtplatform.dispatch.server.guice.request.DefaultRequestProvider.<init>(DefaultRequestProvider.java:
35)
at
com.gwtplatform.dispatch.server.guice.DispatchModule.configure(DispatchModule.java:
135)

Although I'm not sure 100% why some HttpServletRequest needs to be
instantiated, I understand that it's complaining about some missing
Provider for HttpServletRequest, hence me trying the following
solution that ends up working:

private HttpServletRequest servletRequest =
mock(HttpServletRequest.class);

@Before
public void setUp() throws Exception {
//...

final Injector injector = Guice.createInjector(new DispatchModule(),
new ServerHandlerModule(),
new MockHandlerModule() {
@Override
protected void configureMockHandlers() {
//...
}
@Provides
public HttpServletRequest createServletRequest() {
return servletRequest;
}
});

dispatcher = injector.getInstance(DispatchAsync.class);

//...
}

Note also how I'm passing the actual app's ServerHandlerModule to the
injector. This allows to spot during unit testing that some bindings
between actions and action handlers are potentially missing.
I hope this will help people writing their first presenters unit
tests!

Cheers.
Luc

Christian Goudreau

unread,
Apr 23, 2011, 1:05:30 PM4/23/11
to gwt-pl...@googlegroups.com
If you want to go further into testing :

Another tool that I use to mock my dispatcher in unit test:

Btw, homequest is an open source project done by me and some fellow students. You can look at it as much as you want. There's one iteration left to do to add documentation, unit test, mavenize and some cleanup.

Cheers,
--
Christian Goudreau

dindeman

unread,
Apr 23, 2011, 11:29:40 PM4/23/11
to GWTP
Hey Christian.

Thanks a lot for the below resources, the arcbees post on testing the
view is really interesting!
Sure about homequest, will do but first... I will incorporate Juckito
into my project. I can't believe I didn't know that tool yet, it seems
great!

As for me I came across gwt-test-utils about a year ago. It's an open
source project developed and maintained by a French company called
Octo. It basically allows you to run "all" GWT JSNI-dependent classes
into the JVM by patching them... plus so much more. It's quite
amazing, it def. kills GwtTestCase as a unit test tool. Have you ever
heard/tried it?
http://code.google.com/p/gwt-test-utils/
I mean of course it's a continuous effort to patch the JSNI code
that's left to be patched, but they seem to do it with some help from
the community. Amazing and at least it gets you out of the woods when
you reach the limits of code splitting through using smart design
patterns and GIN.

Regards.
Luc


On Apr 24, 12:05 am, Christian Goudreau <goudreau.christ...@gmail.com>
wrote:
> If you want to go further into testing :http://arcbees.wordpress.com/2010/11/25/testing-views-using-gwt-platf...
>
> Another tool that I use to mock my dispatcher in unit test:http://code.google.com/p/homequest/source/browse/test/ca/ulaval/equip...
>
> Btw, homequest is an open source project done by me and some fellow
> students. You can look at it as much as you want. There's one iteration left
> to do to add documentation, unit test, mavenize and some cleanup.
>
> Cheers,
>
>
>
>
>
>
>
>
>
> On Sat, Apr 23, 2011 at 12:40 PM, dindeman <dinde...@googlemail.com> wrote:
> > Hi everyone, Philippe, Christian.
>
> > Just wanted to share something I just did in the context of unit
> > testing.
> > I was following the instructions on the wiki page
> >http://code.google.com/p/gwt-platform/wiki/UnitTestingin order to

Christian Goudreau

unread,
Apr 24, 2011, 9:58:25 AM4/24/11
to gwt-pl...@googlegroups.com
Nope I didn't know this tool ! :D Well, I never needed it either, Jukito + MockingBinder allow me to test almost everything. What I can't test is left to integration test (Selenium, etc) 99.99% of the times meaning that I shouldn't even bother to test it as a unit test.

Thanks for sharing :D Jukito is also done by us :)

Cheers,
--
Christian Goudreau

dindeman

unread,
Apr 26, 2011, 1:45:58 AM4/26/11
to GWTP
Hey Christian.

I was following the article you wrote ('Testing views using Gwt-
Platform’s MockingBinder tool') and something a bit weird happened to
my non-view widgets.
As soon as I turned all my views into using binder injection as
described in the article... it broke all my non-view widgets that were
using injection.
For instance I had a composite UiBinder widget (that isn't a view,
juts a widget + ui.xml) and that was using GIN to access a CssResource
upon construction:

public class MyWidget extends Composite {

interface Binder extends UiBinder<Widget, MyWidget> {}
private static Binder binder = GWT.create(Binder.class);

private final Style style;

@Inject
public MyWidget(final Style style) {
initWidget(binder.createAndBindUi(this));
this.style = style;
}
}

After turning all my GWTP's view into using GIN to inject the binder,
the above class would stop compiling and I'd get the following well
known error:
'MyWidget has no default (zero args) constructor. To fix this, you can
define a @UiFactory method on the UiBinder's owner, or annotate a
constructor of MyWidget with @UiConstructor.'
For now I stopped using GIN with my non-view widgets, so in this
particular case I now have:

public class MyWidget extends Composite {

interface Binder extends UiBinder<Widget, MyWidget> {}
private static Binder binder = GWT.create(Binder.class);

private final Style style = Resources.INSTANCE.style();

public MyWidget() {
initWidget(binder.createAndBindUi(this));
}
}

I can live with that but is it an expected behaviour ?

Regards.
Luc

On Apr 24, 12:05 am, Christian Goudreau <goudreau.christ...@gmail.com>
wrote:
> If you want to go further into testing :http://arcbees.wordpress.com/2010/11/25/testing-views-using-gwt-platf...
>
> Another tool that I use to mock my dispatcher in unit test:http://code.google.com/p/homequest/source/browse/test/ca/ulaval/equip...
>
> Btw, homequest is an open source project done by me and some fellow
> students. You can look at it as much as you want. There's one iteration left
> to do to add documentation, unit test, mavenize and some cleanup.
>
> Cheers,
>
>
>
>
>
>
>
>
>
> On Sat, Apr 23, 2011 at 12:40 PM, dindeman <dinde...@googlemail.com> wrote:
> > Hi everyone, Philippe, Christian.
>
> > Just wanted to share something I just did in the context of unit
> > testing.
> > I was following the instructions on the wiki page
> >http://code.google.com/p/gwt-platform/wiki/UnitTestingin order to

Christian Goudreau

unread,
Apr 26, 2011, 7:51:25 AM4/26/11
to gwt-pl...@googlegroups.com
Yeah well, you have to use UiField(provided = true) for those widgets or not use injection.

Personnally I use @UiField(provided = true). There's also an issue about this with gin that would eventually lead to let UiBinder particpate with the @Inject process. Philippe did a couple of experimentation and it was working with Gwt platform, but since gwt 2.2, I don't know if it's still working. Note that it wasn't working by default, you had to use replace with and use our own UiBinder implementation :D

Stick with @UiField(provided = true)  :)

Cheers,
--
Christian Goudreau

dindeman

unread,
Apr 29, 2011, 12:17:12 AM4/29/11
to GWTP
Hey Christian.

Sorry for my late reply here, but thanks for your prompt answer back
then!
Do you mean that I should annotate all injectable fields with
@UiField(provided = true) ?
I have tried that and I still get the '... has no default (zero args)
constructor. To fix this, you can define a @UiFactory ...' error
message.

I remember having researched that topic on the web a little while ago
and I saw many posts of people having the same issue, i.e. struggling
to get GIN and UiBinder work together.
See this thread http://code.google.com/p/google-web-toolkit/issues/detail?id=6151
for instance.

Otherwise the answers always point to the MVP pattern to solve the
issue ;-) But as you know already my question here is about non-MVP'd
small/reusable widgets.

Do you manage to get GIN and UiBinder working fine outside of the
MVP ?

Regards.
Luc

On Apr 26, 6:51 pm, Christian Goudreau <goudreau.christ...@gmail.com>
wrote:
> > > >http://code.google.com/p/gwt-platform/wiki/UnitTestinginorder to

Christian Goudreau

unread,
Apr 29, 2011, 7:37:07 AM4/29/11
to gwt-pl...@googlegroups.com
Do you manage to get GIN and UiBinder working fine outside of the
MVP ?
Yes :D With UiField(provided = true) :)

You have to inject the provided field in the contructor of the view that needs it and assign it before createAndBindUi is called. Here's a small example:

  @UiField @Ignore
  HTMLPanel matriculePanel;
  @UiField
  TextBox matricule;  
  @UiField(provided = true)
  AccountTypeEditor accountType;
  
  private final Driver driver;
  
  @Inject
  public AccountTypeView(final Binder binder, final Driver driver, final AccountTypeEditor accountType) {
    this.driver = driver;
    this.accountType = accountType;
    
    initWidget(binder.createAndBindUi(this));
    
    this.driver.initialize(this);
  }

Cheers,
--
Christian Goudreau
www.arcbees.com

dindeman

unread,
Apr 30, 2011, 6:09:05 AM4/30/11
to GWTP
Well I can't seem to get this working :-| Follows hereunder an example
that fails.
MyWidget is a custom widget that I use once in MyParentView.ui.xml :

public class MyWidget extends Composite {

public interface Binder extends UiBinder<Widget, MyWidget> {}

@Inject
public MyWidget(final Binder binder) {
initWidget(binder.createAndBindUi(this));
}
}

The sole injection of the Binder is causing troubles, there is no
other fields to inject here and MyWidget is basically just an empty
<div>.
When loading the page I'm getting the following error and stack trace:

java.lang.RuntimeException: Deferred binding failed for
'com....client.views.MyParentView$Binder' (did you forget to inherit a
required module?)
at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:
53)
at com.google.gwt.core.client.GWT.create(GWT.java:98)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.create_Key
$type$com$example$gwtpuibinder$client$views$MyParentView$Binder
$_annotation$$none$$(ClientGinjectorImpl.java:2630)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.get_Key
$type$com$example$gwtpuibinder$client$views$MyParentView$Binder
$_annotation$$none$$(ClientGinjectorImpl.java:2644)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.create_Key
$type$com$example$gwtpuibinder$client$views$MyParentView$_annotation$
$none$$(ClientGinjectorImpl.java:1838)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.get_Key
$type$com$example$gwtpuibinder$client$views$MyParentView$_annotation$
$none$$(ClientGinjectorImpl.java:1849)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.create_Key
$type$com$example$gwtpuibinder$client$presenters$MyParentPresenter
$MyView$_annotation$$none$$(ClientGinjectorImpl.java:1521)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.get_Key
$type$com$example$gwtpuibinder$client$presenters$MyParentPresenter
$MyView$_annotation$$none$$(ClientGinjectorImpl.java:1530)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.create_Key
$type$com$example$gwtpuibinder$client$presenters$MyParentPresenter
$_annotation$$none$$(ClientGinjectorImpl.java:2862)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.get_Key
$type$com$example$gwtpuibinder$client$presenters$MyParentPresenter
$_annotation$$none$$(ClientGinjectorImpl.java:2873)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.create_Key
$type$com$example$gwtpuibinder$client$presenters$MainPagePresenter
$_annotation$$none$$(ClientGinjectorImpl.java:720)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.get_Key
$type$com$example$gwtpuibinder$client$presenters$MainPagePresenter
$_annotation$$none$$(ClientGinjectorImpl.java:734)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl.access
$3(ClientGinjectorImpl.java:732)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl
$4.get(ClientGinjectorImpl.java:869)
at com.example.gwtpuibinder.client.gin.ClientGinjectorImpl
$4.get(ClientGinjectorImpl.java:1)
at
com.gwtplatform.common.client.StandardProvider.get(StandardProvider.java:
48)
at
com.gwtplatform.mvp.client.proxy.ProxyImpl.getPresenter(ProxyImpl.java:
46)
at
com.gwtplatform.mvp.client.proxy.RevealContentHandler.onRevealContent(RevealContentHandler.java:
53)
at
com.gwtplatform.mvp.client.proxy.RevealContentEvent.dispatch(RevealContentEvent.java:
78)
at
com.gwtplatform.mvp.client.proxy.RevealContentEvent.dispatch(RevealContentEvent.java:
1)
at
com.google.gwt.event.shared.SimpleEventBus.doFire(SimpleEventBus.java:
204)

Would you have any idea why my app doesn't like it?

Regards.
Luc

On Apr 29, 6:37 pm, Christian Goudreau <goudreau.christ...@gmail.com>
wrote:

Christian Goudreau

unread,
Apr 30, 2011, 11:30:17 AM4/30/11
to gwt-pl...@googlegroups.com
But how MyWidet is added to other widgets ?
--
Christian Goudreau

dindeman

unread,
May 1, 2011, 6:39:39 AM5/1/11
to GWTP
Ah yeah after sending my last message I thought of it and figured out
the issue...
In such as case you have to declare your custom widget as a
UiField(provided = true) where you want to inject it. I mean now that
I'm writing it it makes sense but in fact it's a bit cumbersome.
Cumbersome in the sense that I have these three additional steps to go
through:

* give it a ui:field name inside the view's .ui.xml
* declare it as a view's member with UiField(provided = true)
* inject it through the view's constructor.-

When otherwise I could just add it in the view's .ui.xml without any
other effort and everything works fine.

I mean if you intend to manipulate the widget from the view's code,
it's ok, you can naturally go through these three more steps since
anyway the widget would be declared as a field at the view level.

Anyway anyway, sorry for the noise here. Got it now.
Thank you again Christian !

Cheers.
Luc


On Apr 30, 10:30 pm, Christian Goudreau <goudreau.christ...@gmail.com>
wrote:
> ...
>
> read more »

Christian Goudreau

unread,
May 1, 2011, 9:47:07 AM5/1/11
to gwt-pl...@googlegroups.com
I agree with you, it's cumbersome :D Well, I do this because I know that someday, this issue will be resolve.

No problem for the noise, at least we figured out what was the problem ! hehe

Cheers,
--
Christian Goudreau

Philippe Beaudoin

unread,
May 1, 2011, 10:39:21 AM5/1/11
to gwt-pl...@googlegroups.com
Thanks for summarizing it Luc, I think you nailed the process...
That's exactly what GinUiBinder does, but it's really not mature yet.
I'll come back with the idea sometime in the future... If you're
interested, follow this issue:
http://code.google.com/p/gwt-platform/issues/detail?id=280

Cheers,

Philippe

Reply all
Reply to author
Forward
0 new messages