13
votes

Unfortunately the Mockito documentation lacks of exhaustive information, it's difficult to find the proper way how to create the following setup.

I have a class "ResourceManager" which should be tested. This class instantiates another class "JerseyClient" which has a method called "get". I want "ResourceManager" to not invoke the real "JerseyClient" but a mock (or a stub?) from it (It's already unclear to me what is the difference between mocking and stubbing or mocks and spies in Mockito context).

My attempts are to @Mock (or @Spy?) JerseyClient, or at least one method of it:

@RunWith(MockitoJUnitRunner.class)
public class ResourceManagerTest
{
    @Mock
    private JerseyClient jerseyClient;


    @Test
    public void testResultHandling() throws JsonGenerationException, JsonMappingException, IOException, ResourceException
    {
        TestEntity testEntity = new TestEntity();
        ResourceManager resourceManager = new ResourceManager();

        testEntity.setGet(true);
        testEntity.setTestAttribute("1stTest");

        when(jerseyClient.get(anyString())).thenReturn("{\"get\":true,\"testAttribute\":\"2ndTest\",\"message\":\"success\"}");

//      doReturn("{\"get\":true,\"testAttribute\":\"2ndTest\",\"message\":\"success\"}").when(jerseyClient).get(anyString());

        TestEntity result = (TestEntity)resourceManager.execute(testEntity, TestEntity.class);

        assertThat(result, is(notNullValue()));
        assertThat(result.getMessage(), is("success"));
        assertThat(result.getTestAttribute(), is("2ndTest"));
    }
}

As you can see, I tried to mock jerseyClient.get() method to return a predefined JSON string:

when(jerseyClient.get(anyString())).thenReturn("{\"get\":true,\"testAttribute\":\"2ndTest\",\"message\":\"success\"}");

or

doReturn("{\"get\":true,\"testAttribute\":\"2ndTest\",\"message\":\"success\"}").when(jerseyClient).get(anyString());

But none of them work. That means that the real JerseyClient.get method is invoked, because it tries to make a HTTP request with the real JerseyClient.

What is the solution and what is this what I want to do here? Is it spying on a real object or mocking an object where I want to mock a method of it, and when can I replace methods, only on mocks or only on spies?

1

1 Answers

12
votes

I found the answer on my own. I need to add

@InjectMocks
private ResourceManager resourceManager;

Then I need to run the test with this instance:

@RunWith(MockitoJUnitRunner.class)
public class ResourceManagerTest
{
    @Mock
    private JerseyClient jerseyClient;

    @InjectMocks
    private ResourceManager resourceManager;

    @Test
    public void testResultHandling() throws JsonGenerationException, JsonMappingException, IOException, ResourceException
    {
        TestEntity testEntity = new TestEntity();

        testEntity.setGet(true);
        testEntity.setTestAttribute("1stTest");

        when(jerseyClient.get(anyString())).thenReturn("{\"get\":true,\"testAttribute\":\"2ndTest\",\"message\":\"success\"}");   

        TestEntity result = (TestEntity)resourceManager.execute(testEntity, TestEntity.class);

        assertThat(result, is(notNullValue()));
        assertThat(result.getMessage(), is("success"));
        assertThat(result.getTestAttribute(), is("2ndTest"));
    }
}

And I can also use the "doReturn...when" pattern.