Better Software - November 2008 - (Page 29) @RunWith(JMock.class) public class PresenterTest { Mockery context = new Mockery(); @Test public void anUnavailableRoomDisablesTheSaveButton() { final MeetingView view = context.mock(MeetingView.class); final RoomScheduler scheduler = context.mock(RoomScheduler.class); final Meeting meeting = new Meeting(); final Presenter presenter = new Presenter(meeting, view, scheduler); // The schedule service will reply with no available capacity context.checking(new Expectations() { { allowing(scheduler).canAcceptCapacityFor(meeting); will(returnValue(false)); one(view).disableSaveButton(); } }); presenter.requiredCapacityChanged(new FakeTextContainer(“225”)); assertEquals(“Should have updated the model’s capacity”, 225, meeting.getCapacity()); } } Listing 3 including the expected capacity and date. The application will check with a scheduling back-end service to determine if the room is available. If it’s not available, the Save button will dim and a message will be displayed. See figure 1 for a sample layout of this dialog. After some quick drawing at a whiteboard, we come up with a rough sketch of the objects involved, as shown in figure 2. Building the Presenter The key to testing presenters is to keep in mind that they are plain old Java code and can be tested like any other Java code with JUnit. A mock-object library like JMock [5] can be used to test the interactions between the presenter and the view components. Let’s tackle a small slice of the following functionality: The user enters a meeting capacity that cannot be scheduled. First, the view will notify the pre- senter that the user changed the value of the capacity text field. The presenter will then ask the RoomScheduler service if it can accept a new meeting with the specified capacity. Finally, the presenter will tell the view to disable the Save button. Listing 3 shows a test for this scenario. This is an interaction-based test using JMock to provide test doubles for the MeetingView and the RoomScheduler. We stub out the scheduler to reply that it cannot accept the capacity for the meeting and expect our view to be told to disable the Save button. Note here that the view ends up being fairly dumb; it does nothing but notify the presenter whenever the required capacity is changed. This code requires that we specify an interface for our view: public interface MeetingView { void disableSaveButton(); } and for our service: public interface RoomScheduler { boolean canAcceptCapacityFor( Meeting meeting); } The code that passes this test is fairly simple, as shown in listing 4. The presenter is responsible for orchestrating the call to the remote service and instructing the view to disable the Save button. Note also that we’re choosing to let the presenter maintain the state of the Meeting object, so that all UI events ultimately modify this object. This is a very simple implementation, but it’s far from the completed design. Our next test would probably check that setting an acceptable capacity enables the Save button and drives us to make either a new enableSaveButton method or a generalized setSaveButtonAvailable method on the view. We’re still testing NOVEMBER 2008 BETTER SOFTWARE www.StickyMinds.com 29 http://www.StickyMinds.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.