0

I'm learning JUnit, but shouldn't assertTrue(..) be used like this :

anObject myObject=anObject();
myObject.assertTrue(...);

The part I don't quite understand is, in an OO language, where suddenly comes this method call without an object, it seems it implies JUnit.assertTrue(...), that's how I understand it, but this is nowhere mentioned, am I correct ?

If so, then "Result result = JUnitCore.runClasses(TestJunit.class);" should be like this :

Result result = runClasses(TestJunit.class);

Why the inconsistency ? Am I missing something ?

Emil Sit
  • 22,894
  • 7
  • 53
  • 75
Frank
  • 30,590
  • 58
  • 161
  • 244

2 Answers2

3

First, assertTrue and its relatives (assertFalse, assertThat) are all static methods. One would import the static method of their assertion of choice (and that lives in Assert, so assertTrue is shorthand for Assert.assertTrue).

Second, the assertion takes place with respect to the object, but not as a property of it. In my mind, it does not make sense to conduct assertions to a concrete object if the assertion is an actual property on the object.

Third, when you're retrieving your result (which I presume is what you're doing), you want the answer from the concrete object you're testing. I don't understand your construct for retrieving Result back, since what you intend to test in a unit test is just some unit of code - something small, straightforward to verify, and something that does not actively interfere with refactoring efforts.


Here's how I would normally write unit tests. Hopefully this provides you some clarification as to what I want out of my tests, and what I'd be testing.

Use case: I have written a utility to retrieve the set difference between two Lists, with the obvious caveat that there may be duplicates. This is some code I recall putting together for another answer, but I liked it enough that I refined it, and wrote tests to ensure behavior.

public static List<Integer> difference(List<Integer> leftList, List<Integer> rightList) {
    if(null == leftList || null == rightList) {
        throw new IllegalArgumentException("Can't have any null parameters.");
    }
    if(leftList.size() < rightList.size()) {
        throw new IllegalArgumentException("Left shouldn't be larger than right.");
    }

    List<Integer> result = new LinkedList<>();
    int i = 0;
    int j = 0;
    while (i < leftList.size()) {
        while (j < rightList.size()) {
            Integer leftElement = leftList.get(i);
            Integer rightElement = rightList.get(j);
            if(rightElement.compareTo(leftElement) <= 0) {
                // less than or equal to.  Skip.
                i += 1;
                j += 1;
                break;
            }
            if(rightElement.compareTo(leftElement) > 0) {
                // The right-hand side is greater than the left hand side.
                // Add it to the results.
                result.add(leftElement);
                i++;
                break;
            }
            j++;
        }
    }
    return result;
}

Here's what the unit tests are like. Notice how I'm asserting, in principle, one thing. It violates some principle of OO, but when you're writing tests, you want to assert behavior and results.

@Test
public void testDifference() throws Exception {
    //given
    List<Integer> left = Lists.newArrayList(1, 2, 3, 4, 5);
    List<Integer> right = Lists.newArrayList(1, 2, 4, 5);

    //when
    List<Integer> result = SetUtils.difference(left, right);

    //then
    assertEquals(Lists.newArrayList(3), result);
}

@Test
public void testDifference2() throws Exception {
    //given
    List<Integer> left = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 9, 10);
    List<Integer> right = Lists.newArrayList(1, 2, 4, 5, 10);

    //when
    List<Integer> result = SetUtils.difference(left, right);

    //then
    assertEquals(Lists.newArrayList(3, 6, 7, 9), result);
}

If you've continued down this far, let me illustrate one of the benefits to writing the unit tests in this behavior. If I wanted to forego the use of the while loop, and instead use foreach, I could now perform that refactoring with confidence; the way that the unit tests are structured allows me to, at a glance, see and expect the behavior I honestly want from this code.

I couldn't honestly imagine trying to do that if the validity were a part of the static state. That would be tough to pull off.

Makoto
  • 104,088
  • 27
  • 192
  • 230
1

In this case assertTrue is a static method, defined in Assert.java.

Your source will typically import static org.junit.Assert.*; thus making all the static methods from the Assert class available inside the test source. You can also, as is done in the JUnit Getting Started guide, statically import just a single method, such as the assertEquals method. Static imports were introduced in Java 1.5.

OO-ish languages oftne provide a way to write methods that do not operate on a specific instance of an object (for example, Smalltalk or Scala).

Community
  • 1
  • 1
Emil Sit
  • 22,894
  • 7
  • 53
  • 75