This post is intended to be the next steps towards a TDD approach with GWTP. We’ll try to show you the patterns and workflow of writing a GWTP application in a TDD fashion.
- Understanding MVP and GWTP.
- Understanding the basics of JUnit and Jukito.
- (Optional) Understanding Test driven development.
In GWTP, most tests are focused on the Presenter. This is mainly due to the fact that the Presenter can be seen as a bridge between the display and the business logic.
In this posts we will go through these specific topics:
- Interactions Presenter → View
- Interactions View → Presenter
- Interactions with the PlaceManager
- Interactions with the EventBus
The first case is to populate the view with data taken from a client side service or a backend. Let’s say we want to fill a label with the name of a user.
When data doesn’t need to change once a Presenter is bound, it is a good idea to put the expensive work in the
onBind() method. Here’s how we would write the test and then the Presenter code.
You may have noticed that we don’t include a test for the view here. The reason is fairly simple: we do not write it at all. This is justified by the fact that views usually don’t have much logic; they’re pretty “dumb”. Pass a value or an object to the view and then assign it to a field.
Besides, to be able to write a test case for a view class, one would need to use
GWTTestCase or something similar to be able to inspect the content of the DOM. We personally don’t recommend doing this. View tests often happen to be brittle and thus hard to maintain, and don’t bring much value to the developer.
The second case comes from user interactions with the View (ie: click events, text change events, etc.) It first starts with a handler triggered in the View (which you don’t test because of the reasons mentioned earlier) that will call a method on its
UiHandlers (most likely, a Presenter).
To continue our example, let’s have a text box and a button in the view that will let the user update the username label. This is one of the most common cases when developing Web applications (fetching, saving, displaying data). The flow should go like this:
- The user clicks on the
- The View grabs the new name from the text box’s value
- The View calls its UI handler with the new value
- The Presenter delegates the save request to the service.
- The Presenter tells the view to display the new name
- The View displays the new name in the label
Here’s how it looks like:
The interactions with the
PlaceManager are caused by two scenarios:
- Displaying different information based on the place (nametoken and parameters)
- Changing the current place
For the first one, this decision is made in the
prepareFromRequest method of a
Presenter. This method receives the new
PlaceRequest object containing the nametoken and the parameters.
Let’s adapt our current example so that, now, we have multiple users in the system, and based on the ID parameter that is passed in the
PlaceRequest, we have to display that specific user’s information.
Our first test will need to check that the view displays the correct user’s information, based on an ID received as a parameter. Here’s how it looks like:
And now we have to implement this in our Presenter:
The other type of interaction is when you want to reveal a particular place. Currently, you have to know the exact URL to be able to edit a user’s information. There’s no homepage, so let’s add another page containing the list of users with the proper link to edit the users’ name. This will also be the place to return to once we save a user, using the
PlaceManager. You can get an overview of the complete code here.
When interacting with the
EventBus, there are two kinds of actions you want to verify : firing and handling an event.
We added a delete button to remove the users from the page. We’ll see how the
UserService fires an event when a user gets deleted, and how the
UsersPresenter handles that situation.
Here’s the code of the event we want to raise, and its handler:
Now we want to adapt the
UserService to fire that event when needed. Let’s write the test for that:
And now implement it:
Now in the Presenter, we have to handle that. Let’s write the tests to wire the
UiHandlers and the Presenter.
As you can see here, there’s a little trick with Jukito that we have to add (the
JukitoModule part), so that the
onBind()method doesn’t get called automatically when running the test. We’ll talk a little bit more about this at the end of the post.
And then the event handling:
Finally, the implementation:
As a bonus, here’s the final code with a working view.
With this post, you should now be able to understand how to write basic tests in a TDD workflow in GWTP. There are a couple more complex scenarios that we’ll talk about in the next posts. Namely, testing communication with a server using REST-Dispatch and also tricks, tips and gotchas with Jukito, like the
JukitoModule configuration that you saw in the examples above.
Note that we would have designed the application a bit differently if it were for a real project, but this was mostly for the sake of the demonstration.