msfk
msfk

Reputation: 137

Java Mockito - How to test a method which is calling a method in the same class as well as a method from other class?

I have the code structure like this. Method methodToTest in ClassA is calling a method in ClassA as well well as a method in ClassB

public class ClassA {
    @Autowired
    ClassB classB;

    public void methodToTest() {
        Object c = methodInA();
        Object d = classB.methodInB(c);
    }

    public Object methodInA() {
        //do something
    }
}

public class ClassB {
    public Object methodInB(Object obj) {
        //do something
    }
}

I was trying to mock both calls i.e. call to methodInA and to methodInB

Following is the unit-test code

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class ClassATest {
    @InjectMocks
    ClassA classA;

    @Mock
    ClassB classB;

    @Spy
    ClassA classASpy;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    //Test method in ClassA
    @Test
    public void testMethodInA() {
        Object mockObjA = mock(Object.class);
        Object mockObjB = mock(Object.class);

        doReturn(mockObjA).when(classASpy).methodInA();
        when(classB.methodInB(mockObjA)).thenReturn(mockObjB);

        classA.methodToTest();

        //assertions
    }

}

On running the test, Object c is null but I want it to be equal to mockObjA.

I tried invocation with classASpy.methodToTest() also from the test. But then it gives NullPointerException at line Object d = classB.methodInB(c) in methodToTest().

What will be the correct way to test such scenario?

Upvotes: 0

Views: 2140

Answers (1)

SpaceTrucker
SpaceTrucker

Reputation: 13556

When you are invoking methodToTest you are testing the unit ClassA. It doesn't make much sense to alter the unit under test by mocking something of that unit. Because then you would test something completely different then ClassA.

What you should do is to test that classB.methodInB is invoked with the correct argument. You do this by using an ArgumentCaptor for the argument of invocation classB.methodInB.

ArgumentCaptor<Object > argument = ArgumentCaptor.forClass(Object .class);
verify(mockObjB).methodInB(argument.capture());
Object capturedArgument = argument.getValue();

Then you make assertions on capturedArgument that verify that ClassA.methodInA worked correctly.

Upvotes: 2

Related Questions