junitmockitotddassertdesign-guidelines

Best way to test a method's outcome with JUnit and Mockito


I am trying to test the method:

@Override
    public boolean test(Apple apple) {
        if (apple == null) {
            return false;
        }
        return "green".equals(apple.getColor());
}

My first guess was to test it in the following way:

package io.warthog.designpatterns.behaviorparameterization.impl;

import io.warthog.designpatterns.behaviorparameterization.Apple; import org.junit.Test;

import static org.mockito.Mockito.when;

public class AppleGreenColorPredicateTest {

    private AppleGreenColorPredicate classUnderTest = new AppleGreenColorPredicate();

    @Test
    public void test_WithGreenApple_ReturnsTrue() {
        Apple apple = new Apple();
        apple.setColor("green");
        when(classUnderTest.test(apple)).thenReturn(true);
    }

}

But it gave me the error message:

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles);

So I ended up doing:

package io.warthog.designpatterns.behaviorparameterization.impl;

import io.warthog.designpatterns.behaviorparameterization.Apple; import org.junit.Assert; import org.junit.Test;

public class AppleGreenColorPredicateTest {

    private AppleGreenColorPredicate classUnderTest = new AppleGreenColorPredicate();

    @Test
    public void test_WithGreenApple_ReturnsTrue() {
        Apple apple = new Apple();
        apple.setColor("green");
        Assert.assertEquals(true, classUnderTest.test(apple));
    }

}

The question here is, when would you recommend using the Mockinto.when() approach and when the Assert.equals().

Any help will be greatly appreciated!


Solution

  • I'd follow the XP rule of doing the simplest thing that could possibly work. You don't need to mock anything, so just use the objects directly.

    private AppleGreenColorPredicate classUnderTest;
    
    @Before
    public void setUp() {
        classUnderTest = new AppleGreenColorPredicate();
    }
    
    @Test
    public void nullTest() {
        assertFalse(classUnderTest.test(null));
    }
    
    @Test
    public void green() {
        Apple a = new Apple();
        a.setColor("green");
        assertTrue(classUnderTest.test(a));
    }
    
    @Test
    public void notGreen() {
        Apple a = new Apple();
        a.setColor("red");
        assertFalse(classUnderTest.test(a));
    }
    

    In your mockito code, you seem to be mocking what you're testing, i.e., you won't discover any problems in your code because your test only calls the mocks. That gives a false sense of security. Only mock when you have to. Mock the dependencies of the class under test, not the actual class under test.