Skip to content

Wakaleo Consulting

  Home Blog Junit Parameterized Tests and Hamcrest Asserts - a potent mix!
  • Expertise in quality development and testing practices
  • Expertise in Continuous Integration and Continuous Delivery
  • Training and Mentoring in Test Driven Development
  • Expertise in Automated Acceptance Tests and ATDD
  • Training and Mentoring in Test Driven Development
  • Training and Mentoring in Test Driven Development
  • Training and Mentoring in Test Driven Development
  • Expert Jenkins/Hudson training and mentoring
  • Expertise in Continuous Integration and Continuous Deployment
Junit Parameterized Tests and Hamcrest Asserts - a potent mix! PDF Print E-mail
Sunday, 26 September 2010 03:31

A recent question on Twitter about my JUnit Kung Fu talk got me thinking - is it possible to combine the expressivity of Hamcrest asserts with the power of parameterized testing? The answer is, of course, yes. Hamcrest expressions are not limited to assertThat statements - they can be used in isolation as well.

For example, here is a simple example of how you can use JUnit 4 parameterized tests in combination with Hamcrest matchers to match not only values, but expressions:

@RunWith(Parameterized.class)
import java.util.Arrays;
import java.util.Collection;

import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.*;

public class ParameterizedTestWithMatchersTest {

  private int value;
  private Matcher expectedValue;

  @Parameters
  public static Collection data() {
    return Arrays.asList(new Object[][] {
        { 1, greaterThan(0) },
        { 0, not(greaterThan(1)) },
        { 2, allOf(greaterThan(1), lessThan(3)) },
        { 4, allOf(greaterThan(1), lessThan(3)) },
    });
  }

  public ParameterizedTestWithMatchersTest(int value, 
                                           Matcher expectedValue) {
    this.value = value;
    this.expectedValue = expectedValue;
  }
  
  @Test
  public void valueShouldMatchExpectations() {
    assertThat(describeExpectations(), 
               expectedValue.matches(value), is(true));
  }

  private String describeExpectations() {
    return Integer.toString(value) 
           + " should be " + expectedValue.toString();
  }
}

I've added a describeExpectations() method to make any error methods take advantage of Hamcrest's nice error reporting features:

java.lang.AssertionError: 4 should be 
(a value greater than <1> and a value less than <3>)
Expected: is <true>
     got: <false>

Of course, typically you would process the input data before comparing it to the expected outcome, so you would probably tailor this method to make it more relevant to the task at hand:

@RunWith(Parameterized.class)
public class ParameterizedTestWithMatchersTest {

  private int value;
  private Matcher expectedValue;

  @Parameters
  public static Collection data() {
    return Arrays.asList(new Object[][] {
        { 3, is(9) },
        { 1, is(greaterThan(0)) },
        { 0, is(not(greaterThan(1))) },
        { 2, allOf(greaterThan(3), lessThanOrEqualTo(4)) },
        
    });
  }

  public ParameterizedTestWithMatchersTest(int value, 
                                           Matcher expectedValue) {
    this.value = value;
    this.expectedValue = expectedValue;
  }
  
  private int squareOf(int value) {
    return value * value;
  }
  
  @Test
  public void valueShouldMatchExpectations() {
    int valueSquared = squareOf(value);
    assertThat(describeExpectations(), 
               expectedValue.matches(valueSquared), is(true));
  }

  private String describeExpectations() {
    return "The square of " + Integer.toString(value) 
                            + " should be " + expectedValue.toString();
  }
}

I'm not sure what the use case for this would be - typically I use parameterized tests with very specific expected values. But I'm sure someone will think of something ;-) .

Tags See All Tags Add New Tag...

Please Enter New Tags Separated By Comma's
  Or Close

JUnit  TDD  Testing  Unit Testing  Unit Tests 

Trackback(0)
Comments (0)Add Comment

Write comment

busy