Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Mockito to mock a class method inside another class

I'm trying to write unit tests with Mockito / JUnit for a function like this:

class1 {
 method {
  object1 = class2.method // method that I want to fake the return value
  // some code that I still want to run
 }
}

Is there any way in Mockito to stub the result of class2.method? I'm trying to improve code coverage for class1 so I need to call its real production methods.

I looked into the Mockito API at its spy method but that would overwrite the whole method and not the part that I want.

like image 920
Chang Liu Avatar asked Jul 23 '15 19:07

Chang Liu


People also ask

Can Mockito mock a class?

The Mockito. mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called.

What is the difference between @mock and @InjectMocks?

@InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock annotations into this instance. @Mock is used to create mocks that are needed to support the testing of the class to be tested. @InjectMocks is used to create class instances that need to be tested in the test class.

How do you mock a method call inside another method in the same class?

We can mock runInGround(String location) method inside the PersonTest class as shown below. Instead of using mock(class) here we need to use Mockito. spy() to mock the same class we are testing. Then we can mock the method we want as follows.

Can I mock private methods using Mockito?

For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.


2 Answers

I think I am understanding your question. Let me re-phrase, you have a function that you are trying to test and want to mock the results of a function called within that function, but in a different class. I have handled that in the following way.

public MyUnitTest {
    private static final MyClass2 class2 = mock(MyClass2.class);

    @Begin
    public void setupTests() {
        when(class2.get(1000)).thenReturn(new User(1000, "John"));
        when(class2.validateObject(anyObj()).thenReturn(true);
    }

    @Test
    public void testFunctionCall() {
        String out = myClass.functionCall();
        assertThat(out).isEqualTo("Output");
    }
}

What this is doing is that within the function wrapped with the @Before annotation, I am setting up how I want the functions in class2 to respond given specific inputs. Then, from within the actual test, I am just calling the function that I am trying to test in the class I want to test. In this case, the myClass.functionCall() is running through as normal and you are not overwriting any of its methods, but you are just mocking the outputs that it gets from the methods (or method) within MyClass2.

like image 163
John Brumbaugh Avatar answered Oct 24 '22 00:10

John Brumbaugh


This Worked for Me:

public class Class1Test {

  Class1 class1;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    class1 = new Class1();
  }

  @Test
  public void testClass1Method() {

    Class2 class2 = Mockito.mock(Class2.class);
    class1.setClass2(class2);
    Mockito.when(
            class2.class2Method(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn("some response");

    String actualResponse = class1
            .class1Method("12345", "3333", "4444");
    assertEquals("some response", actualResponse);
  }
}
like image 44
krku Avatar answered Oct 24 '22 00:10

krku