Unit testing GWT

by dan on May 15, 2009

Unit testing GWT can be very difficult.  Let me start by saying I don’t consider tests that use com.google.gwt.junit.client.GWTTestCase to be unit tests, I consider them to be integration tests.  This article is about compiling your GWT code into java bytecode and running it just like any other unit test.  Here’s why you’d want to do this:

  1. Your test will execute quickly.
  2. You can use any testing framework you want instead of being forced to use JUnit.
  3. As you’ll see, you can leverage GWT to mock some dependencies for you.

The first thing we’ll be doing is creating our own GWTMockUtilities class.  GWT already comes with one of these, but it isn’t ideal for our needs.  This class allows us to use GWT.create(…); in Java bytecode without exceptions being thrown.  If you were to call this in a class compiled by the Java compiler, you’d get a runtime exception that says this:

          ERROR: GWT.create() is only usable in client code!  It cannot be called,
              for example, from server code.  If you are running a unit test,
              check that your test case extends GWTTestCase and that GWT.create()
              is not called from within an initializer or constructor.

Lies! GWTMockUtilities also prevents this exception from occurring.  Here’s our version of GWTMockUtilities with a minor change.

import com.google.gwt.core.client.GWTBridge;
import com.google.gwt.core.client.GWT;
 
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
 
/**
 * This is almost an exact copy of GWT's com.google.gwt.junit.GWTMockUtilities except it uses our own GWTWidgetBridge
 */
public class GWTMockUtilities {
  public static void disarm() {
    GWTBridge bridge = new GWTWidgetBridge(); /** our change **/
    setGwtBridge(bridge);
  }
 
  public static void restore() {
    setGwtBridge(null);
  }
 
  private static void setGwtBridge(GWTBridge bridge) {
    Class gwtClass = GWT.class;
    Class[] paramTypes = new Class[] {GWTBridge.class};
    Method setBridgeMethod = null;
    try {
      setBridgeMethod = gwtClass.getDeclaredMethod("setBridge", paramTypes);
    } catch (NoSuchMethodException e) {
      throw new RuntimeException(e);
    }
    setBridgeMethod.setAccessible(true);
    try {
      setBridgeMethod.invoke(gwtClass, new Object[] {bridge});
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException(e);
    }
  }
}

Why do we need to change this line? Well the normal GWTMockUtilities will change GWT.create(…)  so that it always returns null instead of throwing an UnsupportedOperationException.  Certainly, this is better, but it tends to cause NullPointerExceptions all over the place, especially if you have any logic in your constructors.

Our GWTWidgetBridge returns a mock of the class you tried to create instead of null.  This gets rid of all of those NullPointerExceptions.

import com.google.gwt.core.client.GWTBridge;
import com.google.gwt.dev.About;
import static org.mockito.Mockito.*;
 
/**
 * This is an exact copy of com.google.gwt.junit.GWTDummyBridge except
 * it returns mocked Widgets instead of null's
 **/
public class GWTWidgetBridge extends GWTBridge {
    @Override
    public  T create(Class classLiteral) {
        return (T) mock(classLiteral); /** Mock what we create.  This used to return null. **/
    }
 
    @Override
    public String getVersion() {
        return About.GWT_VERSION_NUM;
    }
 
    @Override
    public boolean isClient() {
        return false;
    }
 
    @Override
    public void log(String s, Throwable throwable) {
        System.out.println(s);
    }
}

As you can see, I used my favorite Java mocking framework, Mockito. But, I assume you can use your favorite Java mocking framework, too (BTW, your favorite Java mocking framework should be Mockito).  Lets look at this in action.  Here’s some code that we want to test:

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
 
import java.util.Set;
 
public class Unit extends Composite {
 
    protected ListBox listBox1;
    protected TextBox textBox1;
    protected ListBox listBox2;
    protected HTML html1;
    protected Button button1;
    protected CustomFlexTable flexTable;
 
    public Unit() {
        initialize();
        compose();
        initWidget(flexTable);
    }
 
    private void initialize() {
        listBox1 = GWT.create(ListBox.class);
        textBox1 = GWT.create(TextBox.class);
        listBox2 = GWT.create(ListBox.class);
        html1 = GWT.create(HTML.class);
        button1 = GWT.create(Button.class);
        flexTable = GWT.create(CustomFlexTable.class);
    }
 
    private void compose() {
        flexTable.setCellSpacing(0); /** Under normal circumstances, this would cause a NPE **/
 
        flexTable.setWidget(0, 0, listBox1);
        flexTable.setWidget(0, 1, textBox1);
        flexTable.setWidget(0, 2, listBox2);
        flexTable.setWidget(0, 3, button1);
        flexTable.setWidget(1, 0, html1);
        flexTable.setColSpan(1, 0, 4);  /** normally would be flexTable.getFlexCellFormatter().setColSpan(1, 0, 4); To be discussed... **/
    }
 
     //and so on...
}

And here’s how we start our unit test (using Testng):

public class MyTest {
    private Unit unit;
    private HTML html1;
    private TextBox textBox1;
    private ListBox listBox1;
    private ListBox listBox2;
 
    @BeforeMethod
    public void setUp() {
        GWTMockUtilities.disarm();  /** Use our GWTMockUtilities **/
 
        unit = new Unit();
        listBox1 = unit.listBox1; /** These have already been mocked for us **/
        textBox1 = unit.textBox1;
        html1 = unit.html1;
        listBox2 = unit.listBox2;
    }
 
    @AfterMethod
    public void tearDown() {
        GWTMockUtilities.restore(); /** Stop using our GWTMockUtilities (integration tests may appreciate this) **/
    }
 
    @Test
    public void testTrue() {
        assert true;  /** Normally, you can't even get this test to pass because setup fails. **/
    }
 
    //other tests...
}

And with that, we can unit test as if we had written plain old java objects. There are some restrictions on this that may cramp your style.  You have to use GWT.create(…) instead of the new keyword.  You may be used to typing new Label(“FooBar”); in your code. With this method, you’d have to change that to:

Label label = GWT.create(Label.class);
label.setText("FooBar");

The other restriction is related to the CustomFlexTable I’ve created.  This is its source:

public class CustomFlexTable extends FlexTable {
 
    public void setColSpan(int row, int column, int colSpan) {
        getFlexCellFormatter().setColSpan(row, column, colSpan);
    }
}

If I don’t use this class, I would get a NullPointerException.  The reason is that the GWTWidgetBridge we created mock’s the FlexTable but it doesn’t stub out the FlexTable’s getFlexCellFormatter() method.  Mockito reacts by returning null for that method and when we call setColSpan(…) on null, we get a NPE.  In Mockito’s defense, FlexTable is violating the Law of Demeter here. You can argue that the API is the problem.  Also, note that this is only a problem when the constructor calls the compose() method. If the client called the compose method instead of the constructor, we could stub the FlexTable’s getFlexCellFormatter() method before we call compose().

{ Comments on this entry are closed }

My IDE layout for unit tests

by dan on April 2, 2009

my ide layout

my ide layout

I have found this to be a particulary effective way to layout my IDE when I’m writing a unit test.  Let me explain every part in detail.

  • Editor split vertically: This is the key part.  With my editor split vertically, I can keep the test and the production code open at the same time.  Without this split, I’d constantly have to switch between the two files.
  • Test on left & Production on right: I think it makes sense to put the file you type more on on the left side.  Keep in mind I type left to right.
  • Hide file system: The file system takes up precious horizontal space and should be ignored.  I focus just on the test and the unit of code I’m testing.
  • Tested code & Untested code: Code coverage shows me how much of this unit I have tested.
  • Test just this unit: This prevents other integration tests from interfering with the code coverage report.  I want to know how well this unit test covers the production code.

{ Comments on this entry are closed }

Why I prefer Stripes over Wicket

by dan on March 31, 2009

I wrote an article called The top 8 reasons I don’t use Wicket. Turns out it’s a pretty controversial topic (who’d have thought?). In one of the comments, Igor Vaynberg, who contributes a lot to the Wicket framework, responded to my article point by point. I started to write a reply and I realized that it was getting so long that it made sense to just make a new article out of it. My previous article wasn’t about Wicket vs Stripes, but I’m going to make this article about that.

Before I start, I just want to say that when I was using Wicket, Igor was without a doubt the most helpful person on the IRC channel and mailing list. He holds an incredible amount of knowledge about the Wicket framework and is always willing to share it.

1) there are three books available. the mailing lists are indexed by sites like nabble and markmail which make it trivial to search them. google indexes the lists also. the wiki is a wiki – it is user-contributed thus the quality varies – i think everyone understands this and takes it for granted.

I already mentioned this and addressed it in detail. But, more importantly, the difference between Wicket and Stripes is that with Stripes, you’ll be doing a lot less searching in the first place. It’s just easier to use!  In fact, if you read the quick start guide, a mere 3 pages or so, you’ll basically “get” Stripes and pretty much be ready to make a complete webapp right off the bat. When you do have questions, most answers are literally right on the homepage.  Seriously, how much easier can it get?

2) if you have no OO skills, which from reading this post i can clearly see you do not, wicket indeed has a high learning curve because it makes heavy use of OO principles.

you want to override a tag attribute: override the function that generates it Component#onCompoentTag(Tag tag) and use the provided tag object to modify attributes. Or use a provided convenience AttributeModifier to make this easier and shared behavior across component instances.

you want to append something to the head element: override the method that generates it IHeaderContributor#renderHeader(IHeaderResponse response) and use the provided response object to write something into the head. or use the provided convenience HeaderContributors to make this easier and shared behavior across component instances.

you want to make a component’s visibility dynamic? override the method that controls it: Component#isVisible() and return true or false based on your needs.

you want to output dynamic value between some tag’s you attached a component to? override the method that generates that value: Component#onComponentTagBody(..) and use the provided arguments to write out the body. Or use the convenience Label component that makes this easier.

see the pattern now?

Um, poor communication skills? :) Sorry, I’m just kidding. Seriously, IMHO, this isn’t easy or convenient. You know how you do every one of these things in Stripes? A conditional JSTL tag. The same thing you’d do in Struts. The same thing you’d do in any web framework that uses JSPs.

This has three huge advantages:

  1. If you already know JSTL, learning Stripes will be even quicker.
  2. If you don’t know JSTL and you learn Stripes, you learned something that is directly transferable to many other web frameworks. On the other hand, when you learn Wicket, you learned something that is only applicable to Wicket, AFAICT.
  3. There are lots of taglibs out there that are web framework agnostic. You can use these in Stripes even if they weren’t originally intended for it. This knowledge is also directly transferable.

Back to Igor:

3) java code is more structured and thus is easier to maintain, refactor, improve, evolve, and change. the compiler for java is a hell of a lot better at catching errors early then a compiler for
markup..oh, wait, there isnt one.

Yes, I agree. And that’s why I pull as much logic as I possibly can into my Java classes. Sure, display logic has to exist in JSPs: Wicket has that on Stripes. But I consider it worth it. Read the 8 points of my previous post to see why.  Stripes doesn’t have any of these problems.

> Wicket doesn’t have an official list of, “Cool features that will save you tons of time” anywhere, so you’ll likely have the same experience as me.

Wicket’s cool feature is that all the dynamic behavior is in java code. but obviously you didnt get that.

Well Stripes’ cool features are that it’s easy to learn, use and it stays out of your way. Regarding that last point, Stripes is very “thin” but is doing very helpful things behind the scenes (I suggest readers look at this Struts1 vs Stripes article to learn more). Most of the time you barely notice it’s there.

4) apparently tons of people who have created components that integrate from yui to gmaps do not share your opinion. you can see them all in wicketstuff.org.

i bet i can create a component that elegantly integrates this javascript captcha into wicket and makes it transparent. just because you couldnt doesnt mean it is impossible. the awesome thing about wicket is that once i do it i can jar it up and anyone else using wicket can reuse it in their project with little or no effort. let me know if you want to put your money where your mouth is :)

Not really sure where you’re coming from here. I already made a Wicket ReCaptcha library and posted the source on the mailing list. I also already made a Stripes ReCaptcha library and posted the source on the wiki.

But anyway, I’m sure you could have made the Wicket one better than I did. You have the advantage of actually writing part of the framework. But, for those of us that haven’t written the web framework they work in, let me tell you that the Stripes version was much easier to create.

5) why would you use wicket to generate javascript or css? wicket generates xml markup, thats it. if you do want to do this we do provide a texttemplate helper that can be used to generate dynamic text tidbits. there is also velocity panel if you prefer to use velocity for this.

OK, while I go off and google how these two components work I’ll explain how you’d do this in Stripes: A conditional JSTL tag. See the pattern now? :)

6) once again, this goes back to you not having the OO skillset. there is nothing wrong with anonymous classes. the cool thing is that if you find yourself in a situation of writing the same kind of anonymous class over and over you can simply refactor an anonymous class into a top-level class and reuse it. the ide will do all the work for you.

I disagree. Anonymous inner classes are ugly and hard to read. They also make the class that creates them difficult to unit test.

If we’re going to consider the convenience that using an IDE brings the picture, I should point out that there’s a Intellij IDEA plugin that will reduce the potential errors you’d get in JSPs when using Stripes.

7) i am using wicket on a project now where a designer goes into our source tree and modifies the look and feel of the website. he had to work on jsps before and now swears by wicket. this happened on a project i worked previous to this one in a different company. and the same before that. maybe you are a one-man team so you dont see the benefit.

My current company isn’t huge but it’s got > 50 software engineers. But regardless, I already acknowledged on the previous post that Wicket is one of the best frameworks in this category.

Now, that being said… who cares? Seriously, I’ve never worked at any company where the average amount of developer time spent on the appearance of the site even came close to 20%. When I edit JSPs, I spend most of my time adding new forms, inputs, and other miscellaneous dynamic parts to my already existing pages. And that, in my opinion, is where Stripes puts its emphasis on productivity.

I’ll let the readers be the judge by comparing two apps that do the same thing: You enter a field in a form, submit it, and it echos the same message back to you.

Here’s the Wicket version (got the source one of the example pages):

HTML

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Wicket Examples - echo</title>
    <link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
    <span wicket:id="mainNavigation"/>
 
    <form wicket:id="form">
        <input type="text" wicket:id="msgInput" value="" size="50" />
        <input type="submit" value="set message" />
    </form>
    <span wicket:id="msg" id="msg">Message goes here</span>
 
</body>
</html>

Java

package org.apache.wicket.examples.echo;
 
import org.apache.wicket.examples.WicketExamplePage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.PropertyModel;
 
/**
 * The simplest form application possible. Just prints any user input to a label.
 *
 * @author Eelco Hillenius
 */
public class Echo extends WicketExamplePage
{
    private String message = "[type your message to the world here]";
 
    /**
     * Constructor.
     */
    public Echo()
    {
        // This model references the page's message property and is
        // shared by the label and form component
        PropertyModel messageModel = new PropertyModel(this, "message");
 
        // The label displays the currently set message
        add(new Label("msg", messageModel));
 
        // Add a form to change the message. We don't need to do anything
        // else with this form as the shared model is automatically updated
        // on form submits
        Form form = new Form("form");
        form.add(new TextField("msgInput", messageModel));
        add(form);
    }
 
    /**
     * @return the message
     */
    public String getMessage()
    {
        return message;
    }
 
    /**
     * @param message
     *            the message to set
     */
    public void setMessage(String message)
    {
        this.message = message;
    }
}

Here’s the Stripes version:

JSP

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head><title>Echo</title></head>
  <body>
    <stripes:form beanclass="com.example.EchoActionBean">
        <table>
            <tr>
                <td><stripes:text name="message"/></td>
                <!-- ${actionBean} is the actionBean that took you to this JSP. Always an EchoActionBean in this example -->
                <td>${actionBean.message}</td>
                <td><stripes:submit name="printMessage" value="Submit"/></td>
            </tr>
        </table>
    </stripes:form>
  </body>
</html>

Java

package com.example;
 
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
 
@UrlBinding("/home")
public class EchoActionBean implements ActionBean {
    private ActionBeanContext actionBeanContext;
    private String message = "[type your message to the world here]";
 
    public void setContext(ActionBeanContext actionBeanContext) {
        this.actionBeanContext = actionBeanContext;
    }
 
    public ActionBeanContext getContext() {
        return actionBeanContext;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
 
    @DefaultHandler  //Every time you visit "/home", this method gets called and forwards you to the JSP
    public Resolution printMessage() {
        return new ForwardResolution("/WEB-INF/jsp/home.jsp");
    }
}

8) agreed. stateless/bookmarkable stuff IS harder then stateful code in wicket. if you have an app that is totally stateless you should probably not use wicket. however, most apps i worked on, have only a small portion of functionality exposed as public pages, the bulk of the functionality – usually the one with a complex ui – is behind a login page where google cant index it and bookmarkability is not important. you have to choose the right tool for the job.

Just because a webapp is partially or even mostly stateful doesn’t mean you should use Wicket to develop it. Tim Fennell, the creator of Stripes, actually has a comment about this from an awesome article (I highly recommend it, the creators of 11 web frameworks discuss the pros and cons of what they’ve created) written in 2006:

[I]magine a Google homepage where you could pop open multiple search panels and search and page through results etc. in each panel. Each time you hit next on one panel, the whole page would be refreshed, the panel you clicked on updated, and all the other panels left as they were.

Managing a UI like this in a way that is multi-window safe can be very difficult. This is the problem that component-oriented solutions like Wicket and JSF were designed to solve. My view is that for 90%+ of web applications, component-oriented frameworks are overkill, and that for another 9%, AJAX is more a more effective way to manage a stateful UI as described above.

{ Comments on this entry are closed }

How is bloggy formed?

by gerald on March 30, 2009

Assert Interesting is yet another software development blog (or YASDB if you like acronyms, and if you’re a SD then you probably do) written by two guys who like to think about software. We like it so much that we get together every few weeks and talk about it for hours over dinner. Since we have so much to say, we figured we should put some of it up on the Intarwebs where other people might be able to benefit from it, or at least disagree enough to leave comment. Our goal is to discuss a broad range of topics, from programming languages and testing to higher level topics like software design and project management. And that is how bloggy is formed.

{ Comments on this entry are closed }