简体   繁体   中英

Not mocking methods, instead calls original methods (mockito)

This class I want to test..

public class AddNumbers {

    public int add(int a, int b){

        checkNumbers checkobj=new checkNumbers();

        boolean flg = checkobj.check(a, b);

        if(flg == true){

            return a+b;
        }else{

            return 0;
        }
    }

}

Here is the unit test case...

@RunWith(MockitoJUnitRunner.class)
public class AddNumbersTest {

    @Mock
    checkNumbers checkobj;

    @InjectMocks
    AddNumbers addobj = new AddNumbers();


    @Test
    public void testAdd1(){

        int a=10;
        int b=5;

        Mockito.when(checkobj.check(a, b)).thenReturn(true);
        assertEquals(addobj.add(a,b),15);

    }
}

When I running this test case, it calls original method of checkNumbers class instead calling mocked one. I get to know this by putting Sysout in checkNumbers.check() method.

Can anyone highlight, where I m doing the mistake.

checkNumbers is created inside the add method ...

checkNumbers checkobj=new checkNumbers();

The Mockito injection feature ( @InjectMocks ) cannot populate this for you.

In order for Mockito to set checkNumbers to a mock you'll need to allow it to be injected.

For example: move it out of add() and declare it as a class member:

private checkNumbers checkobj;

public int add(int a, int b){
    boolean flg = checkobj.check(a, b);

    if(flg == true){

        return a+b;
    }else{

        return 0;
    }
}

When instructed by the @InjectMocks annotation Mockito will try to inject mocks by one of (in this order):

  1. Constructor injection
  2. Setter injection
  3. Property injection

If you declare checkNumbers as a class member then Mockito will inject is as per #3 above. Alternatively, you could declare a constructor like so ...

private checkNumbers checkobj;

public AddNumbers(checkNumbers checkobj) {
    this.checkobj = checkobj;
}

... and Mockito will inject the mock instance as per #1 above.

This would have the benefit of making your class explicit about any other classes it needs at construction time and could allow you to swap in different implementations of checkNumbers thereby facilitating the composition of different forms of AddNumbers .

More details in the Mockito docs .

The previous answer of @glytching is absolutely correct.

Here is other possible solution with overridden getter method.

public class AddNumbers {
    // This is new method to return a new instance of checkNumbers.
    checkNumbers getCheckNumbers() {
        return new checkNumbers();
    }

    public int add(int a, int b){
        checkNumbers checkobj = getCheckNumbers();
        // do what you need
    }
}

You test has overridden getCheckNumbers():

@RunWith(MockitoJUnitRunner.class)
public class AddNumbersTest {
    @Mock
    checkNumbers checkobj;

    @InjectMocks
    AddNumbers addobj = new AddNumbers() {
        @Override
        checkNumbers getCheckNumbers() {
            return checkobj;
        }
    };


    @Test
    public void testAdd1(){
        int a=10;
        int b=5;

        Mockito.when(checkobj.check(a, b)).thenReturn(true);
        assertEquals(addobj.add(a,b),15);
    }
}

Couple general remarks regarding your code:

  • Name a class starting by capital letter: CheckNumbers .
  • Name variables by full names: flg -> flag .
  • if(flg == true) can be simplified to if(flg)
  • if/esle construction can be simplified to one line solution: return flag ? a + b : 0 return flag ? a + b : 0
  • Avoid magic numbers in test names: testAdd1 -> addShouldSumTwoGivenIntegers() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM