Reputation: 11
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
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
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