Home > Articles > Programming > Java

Crafting Java with Test-Driven Development, Part 11: Making Things Happen

  • Print
  • + Share This
Our poker application shows a simple view with a "deal" button. The only problem is that the button does nothing when clicked! We'll want to deal cards when a user presses the button, but how do we accomplish that in a test-first way? As usual, Jeff Langr has the answers.
From the author of

In the last installment, we built a view class that shows a list of players and their positions around the table. It also shows a button labeled Deal that does nothing. It’s not a pretty interface, but it’ll suffice for now. Later we can hire a Swing layout expert to make things look nice.

We want the user interface to support doing something when a user clicks the Deal button. What should that something be? Well, we don’t know yet, and honestly, we don’t care yet. Our job right now is to finish development of the view class TablePanel.

Adding Behaviors to the View

Dealing with the button click is technically the job of what’s termed the controller. In a classic user interface design, the controller receives events from input devices (including the keyboard and mouse), and delegates these messages to the underlying model as appropriate. The design of Swing typically promotes combining controller and view responsibilities in the same class.

In Swing, you make a button effect behavior by attaching an ActionListener object to it. You implement the behavior in the ActionListener callback method actionPerformed. Usually, when programmers build a Swing class, they attach ActionListener specifics to a button at the same time as they incorporate the button into the view.

Our job in building the TablePanel class is to create a class that can display a view and also receive controller input from that view. Neither of these responsibilities should have to refer to underlying business logic. Instead, changes to the view will be driven by application code, and events from the controller will be broadcast to any application code that cares to listen.

Our TablePanelTest is a client of TablePanel; in fact, it’s the first client. Think of it as providing an example of how a client should interact with a TablePanel object. Our test method, testDeal, shows how a client needs to tell the view to attach a specific behavior to the Deal button (see Listing 1).

Listing 1 testDeal.

private boolean wasClicked;

public void testDeal() {
  JButton button = SwingUtil.getButton(table, TablePanel.DEAL_BUTTON);

  wasClicked = false;
  table.addDealListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
     wasClicked = true;
   }
  });

  button.doClick();
  assertTrue(wasClicked);
}

The behavior we attach to a TablePanel in testDeal serves the need of testing. This client code simply tracks whether the actionPerformed behavior was executed. Here are the steps we take in testDeal:

  1. Create a button.
  2. Initialize wasClicked to false.
  3. Tell the TablePanel object to attach the testing callback.
  4. Emulate pressing the button by calling doClick.
  5. Assert that wasClicked evaluates to true; that is, that our callback actually was executed.

What we’re doing here is providing mock behavior for the purposes of being able to write a test. The code in the ActionListener definition that we pass to the TablePanel object isn’t what our production listener code will look like. But this listener allows us to design an independent TablePanel class. We’re unit testing in a strict sense—using tests to drive the design of a class so that it can act as a standalone unit.

  • + Share This
  • 🔖 Save To Your Account