More Units with MoreUnit

Just over a year ago I wrote a post about working with JUnit in Eclipse. One of the commenters recommended MoreUnit in order to increase testing efficiency even more. Giving it a try I was delighted and the plugin’s keyboard shortcuts were immediately memorized by my autonomic nervous system…

Additionally after using MoreUnit for a while I recognized a slight but notable change in one of my working routines. More precisely it seems that I tend to extract more classes covered by own unit tests during refactorings1 than I did before. As maintaining cohesion results in many small classes2 this is probably a good thing.

Well, one could say ‘MoreUnit, the name says it all’ but as I did not expect it to be meant in that way, I decided this might be a good subject for a post. So let’s have a look at the following example to get started:

class ActionItem extends MouseAdapter  {

  private Label control;
  private Runnable action;
  private boolean mouseDown;

  [...]

  ActionItem( Composite parent, Runnable action ) {
    this.control = new Label( parent, SWT.NONE );
    this.control.addMouseListener( this );
    this.action = action;
  }

  @Override
  public void mouseDown( MouseEvent event ) {
    markMouseDown();
  }

  @Override
  public void mouseUp( MouseEvent event ) {
    handleMouseUp( event );
  }

  private void markMouseDown() {
    mouseDown = true;
  }

  private void handleMouseUp( MouseEvent event ) {
    if( mouseDown && inRange( event ) ) {
      action.run();
    }
    mouseDown = false;
  }

  private static boolean inRange( MouseEvent event ) {
    Point size = ( ( Control )event.widget).getSize();
    return    event.x >= 0 && event.x <= size.x 
           && event.y >= 0 && event.y <= size.y;
  }

  [...]
}

The class is an excerpt of a custom UI control3 and it shows how such a control could implement mouse click behavior. We proceed on the assumption that we have an appropriate unit test case with sufficient coverage up and running. It is also safe to presume that several structural refactoring steps have already taken place before reaching the arrangement of the code snippet above.

Considering the mouse click as a single responsibility it is arguable that it should be separated into its own class. To do so I generally start with an inner class where I move the related methods and fields to. After that I assign an instance of that new type to a new field of the surrounding class as demonstrated in the ActionItem constructor below. Last but not least I fix the now undefined method calls by delegating those calls to the newly created field4:

class ActionItem extends MouseAdapter  {

  private Label control;
  private ClickHandler clickHandler;

  [...]

  ActionItem( Composite parent, Runnable action ) {
    this.control = new Label( parent, SWT.NONE );
    this.clickHandler = new ClickHandler( action );
    this.control.addMouseListener( this );
  }

  @Override
  public void mouseDown( MouseEvent event ) {
    clickHandler.markMouseDown();
  }

  @Override
  public void mouseUp( MouseEvent event ) {
    clickHandler.handleMouseUp( event );
  }

  static class ClickHandler {

    private Runnable action;
    private boolean mouseDown;

    ClickHandler( Runnable action ) {
      this.action = action;
    }

    private void markMouseDown() { [...] }
    private void handleMouseUp( MouseEvent event ) { [...] }
    private static boolean inRange( MouseEvent event ) { [...] }
  }

  [...]

}

By running the ActionItem‘s test case successfully and checking the coverage once again, one can be pretty sure that the extraction described above did not introduce any mistakes. Because of this it feels fairly save to move the ClickHandler finally to its own file.

However now there is a class serving as some kind of ‘subcomponent’ which is only covered indirectly by the ‘main’ component’s test case. I have made the observation that such classes often develop a living of their own. Meaning their functionality expands or they are getting reused by other classes or both. At some point in time it probably gets rather difficult to add meaningful and/or comprehensible tests. This is becauce the test class itself lacks the cohesion which was introduced to the unit under test by splitting it into two.

For that reason I usually create a particular test case for the extracted class right away. Even more as with MoreUnit available this can be achieved quite intuitively, actually providing the new test case automatically with a basic set of test method stubs. Continuing our example we would open the extracted ClickHandler in an editor, press ‘ctrl+j’ 5 and select in the upcomming wizard for which method we would like to have a stub created:

new-test

Pressing finish creates a test case correctly located under the according test source folder of your project 6 that looks – depending on your MoreUnit settings – somewhat like this:

public class ClickHandlerTest {

  @Test
  public void testMarkMouseDown() {
    fail( "Not yet implemented" );
  }

  @Test
  public void testHandleMouseUp() {
    fail( "Not yet implemented" );
  }
}

The stubs may serve as starting point for populating the test case meaningfully from scratch. But mind that there is already a full coverage providing set of tests in the ActionItemTest available. So another possibility is to move the content of the mouse click related tests to the newly created ClickHandlerTest. While the latter now does the thorough testing of the new unit, care has to be taken that there are enough tests left in the ActionItemTest that ensures a proper integration of the ClickHandler7.

Conclusion

Working like this for some time now, I am under the impression that maintainability and further development of my code (including test cases) gradually improves. It can be said of course, that MoreUnit should not be the cruicial factor to decide whether or not to extract a certain responsibility into its own class. But to me it seems it eases the decision to do so, by helping to overcome one’s weaker self, having an appropriate test case for the new class just a few clicks away.

  1. See red/green/refactor mantra of Test Driven Development
  2. Robert C. Martin, Clean Code, Chapter 10: Classes
  3. Although the example has been inspired by my current work I stripped it down to the bare minimum needed for this post
  4. A further refactoring step might be to change the ClickHandler in a way that it extends MouseAdapter or implements MouseListener. After that the click handler itself could be registered as mouse listener at the label replacing the action item. This would eliminate the delegating mouse handler methods in ActionItem completely. However I omit this step here to keep the post in scope
  5. This shortcut is usually used to switch between units under test and their according test cases. As you get used to this quite fast, it somehow serves even more as a ‘missing test reminder’ than the particular decorators do…
  6. With OSGi based systems this also might be a test fragment
  7. Note that the extraction process simplifies the test set up of the mouse click functionality tests. The extracted class has no dependency to a SWT widget derivative in the constructor, which allows to provide e.g. a test set up based on mocks. The latter is not possible without fuss for the ActionItem and therefore setup/teardown methods are needed to create, initialize and dispose of Display/Shell instances for example

 

Reference: More Units with MoreUnit from our JCG partner Frank Appel at the Code Affine blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

One Response to "More Units with MoreUnit"

  1. mehar says:

    Nice Thread :)

Leave a Reply


one + = 8



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close