Kanika
Kanika

Reputation: 11

How can we mock a response from another class using Mockito while unit testing

I have a method to test which is calling another class to get some information:

public ClassToTest {

    public void methodToTest() {
        AnotherClass ac = Factory.getInstance();
        ResponseObj response = ac.anotherMethod();
    }
}

AnotherClass is part of another JAR and I would like to mock the response from it(to be specific mock ResponseObj response)

How can I achieve that using Mockito?

Upvotes: 1

Views: 12291

Answers (2)

Rishav
Rishav

Reputation: 4068

Although the answer by @arsen_adzhiametov is correct and up to the mark I would like to contribute how I do it.

In this case, I am mocking the value of HomeClient which internally is a WebClient that calls out another service for some values.

TestClass.java (Please name it better)

...
import org.mockito.Mockito;
...

class TestClass {
    HomeClient mockHomeClient;

    @BeforeEach
    void setup() {
        mockHomeClient = Mockito.mock(HomeClient.class);
        
        // Axon specific test code. Can ignore if not using Axon.
        fixture = new AggregateTestFixture<>(SomeAgreegate.class);
        fixture.registerInjectableResource(mockHomeClient);
    }
    
    @Test
    void testOpenOperation() throws HomeClientException {
        Mockito.when(mockHomeClient.getXYZ("nice")).thenReturn(2);
        // Do what you will with your code and call the method which you want to test
        // Mockito will mock the `HomeClient` in this case and `getXYZ` will return `2`
        // You can also change the mock response any time in the same function
        Mockito.when(mockHomeClient.getXYZ("nice")).thenReturn(-100);

        // Or specify different results on mock when different values are provided
        Mockito.when(mockHomeClient.getXYZ("nice")).thenReturn(1);
        Mockito.when(mockHomeClient.getXYZ("foo")).thenReturn(100);        
        Mockito.when(mockHomeClient.getXYZ("bar")).thenReturn(0);


    }
}

Upvotes: -1

arsen_adzhiametov
arsen_adzhiametov

Reputation: 696

First you need is to make your class testable. It means you need to extract object creation (AnotherClass ac = Factory.getInstance()) from your methodToTest to instance field or maybe separate method (to be able to mock it), or even better - create object outside of your class and pass it via constructor. As a result, your class under test should look like:

public class ClassToTest {

    private AnotherClass ac;

    public ClassToTest(AnotherClass ac) {
        this.ac = ac;
    }

    public void methodToTest() {
        ResponseObj response = ac.anotherMethod();
        response.smth();
    }
}

Then you need to declare AnotherClass and ResponseObj as fields in test class, and initialize them as a mocks.

AnotherClass ac = Mockito.mock(AnotherClass.class);
ResponseObj responseMock = Mockito.mock(ResponseObj.class);

After that you can mock method call:

when(anotherClassMock.anotherMethod()).thenReturn(responseMock);

At the end your test class should look like:

public class ClassToTestTest {

    private AnotherClass anotherClassMock = mock(AnotherClass.class);
    private ResponseObj responseMock = mock(ResponseObj.class);
    private ClassToTest classToTest = new ClassToTest(anotherClassMock);

    @Test
    public void test() {
        when(anotherClassMock.anotherMethod()).thenReturn(responseMock);

        classToTest.methodToTest();

        verify(responseMock, only()).smth();
    }
}

And in case you couldn't change public API of your ClassToTest, you can use approach with Mockito spy and protected method.

public class ClassToTest {

    public void methodToTest() {
        AnotherClass ac = constructAnotherClassObj();
        ResponseObj response = ac.anotherMethod();
        response.smth();
    }

    protected AnotherClass constructAnotherClassObj() {
        return Factory.getInstance();
    }
}


public class ClassToTestTest {

    private AnotherClass anotherClassMock = mock(AnotherClass.class);
    private ResponseObj responseMock = mock(ResponseObj.class);
    private ClassToTest classToTest = spy(new ClassToTest());

    @Test
    public void test() {
        when(anotherClassMock.anotherMethod()).thenReturn(responseMock);
        when(classToTest.constructAnotherClassObj()).thenReturn(anotherClassMock);

        classToTest.methodToTest();

        verify(responseMock, only()).smth();
    }
}

Upvotes: 6

Related Questions