3

I am not able to mock varargs on an overloaded constructor in Mockito. This is the method I want to test

@Override
  public List<User> fetchDataFromExternalService() {
    return Arrays.asList(this.restTemplate.getForObject(URL, User[].class));
  }

User is a POJO class that has attributes, getters and setters. RestTemplate instance is Spring's Rest Template..

This function is an overloaded function and has the the following methods

1) public <T> T getForObject(java.lang.String url,
                                    java.lang.Class<T> responseType,
                                    java.lang.Object... uriVariables)
                             throws RestClientException

2) public <T> T getForObject(java.lang.String url,
                                    java.lang.Class<T> responseType,
                                    java.util.Map<java.lang.String,?> uriVariables)
                             throws RestClientException

I am trying to mock the first function to return an array of users, but not matter what I try, it always returns null. I don't know what I am doing wrong.

My mocking function.

User user = new User();
Mockito.when(this.restTemplate.getForObject(
        Mockito.anyString(), Mockito.eq(User[].class), (Object[]) Mockito.any())).thenReturn(new User[] {user});

I tried using a custom argument matcher as follows,

Mockito.when(this.restTemplate.getForObject(
        Mockito.anyString(), Mockito.eq(User[].class),
        Mockito.argThat(new MyVarargMatcher()))).thenReturn(new User[] {user});

but it still returned null for me.

  class MyVarargMatcher implements ArgumentMatcher<Object[]>, VarargMatcher {

    @Override
    public boolean matches(Object[] argument) {
      return true;
    }
  }

I tried using the approach in this post, but the method is deprecated.

How to properly match varargs in Mockito

https://static.javadoc.io/org.mockito/mockito-core/2.2.7/org/mockito/ArgumentMatchers.html#any()

Maven configuration

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.13.0</version>
    <scope>test</scope>
</dependency>

How can I resolve this issue?

Kartik
  • 2,541
  • 2
  • 37
  • 59

2 Answers2

3

The following works for me:

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.web.client.RestTemplate;

@RunWith(MockitoJUnitRunner.class)
public class DemoApplicationTests {
    @Mock
    private RestTemplate restTemplate;
    @Test
    public void testy() {
        Mockito.when(restTemplate.getForObject(Mockito.anyString(), Mockito.any(), (Object) Mockito.any())).thenReturn("this works");
        Assert.assertEquals("this works", restTemplate.getForObject("hi", String.class, 42, 45));
    }

}
Jacob Botuck
  • 411
  • 6
  • 22
0

You are right about deprecation, but in the same documentation you could find that you should use ArgumentMatchers.any() and more details about it. So the correct example should be:

Mockito.when(this.restTemplate.getForObject(Mockito.anyString(),
        Mockito.eq(User[].class), ArgumentMatchers.any())).thenReturn(new User[] {user});

If you have varArgs different than Object.class you could specify it to narrow matches ArgumentMatchers.any(String.class).

Working example:

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

public class DocTest {
    @Test
    public void testMockito() {
        DocTest doc = mock(DocTest.class);
        when(doc.getDocs(eq(String.class), any(String.class))).thenReturn("success");
        assertEquals("success", doc.getDocs(String.class));
        assertEquals(null, doc.getDocs(Integer.class));
        assertEquals("success", doc.getDocs(String.class, "failed", "failed"));
        assertEquals(null, doc.getDocs(String.class, new Integer(1)));
    }

    public <T> String getDocs(Class<T> clazz, Object... objects){
        return "";
    }
}
uli
  • 671
  • 6
  • 15
  • AdditionalMatchers does not show "any" in the method API. – Kartik Feb 05 '18 at 07:14
  • You are right, copy past mistake. The correct name is `org.mockito.ArgumentMatchers.any()`. – uli Feb 05 '18 at 07:20
  • Could you share how exactly did you tried? restTemplate should be mocked object. I will update answer with working example. – uli Feb 05 '18 at 13:57