简体   繁体   中英

How to mock resttemplate by mockito

I want to mock a resttemplate request,but it seems not work. Here is the class that i want test:

public class SomeUtil {
    public static OrderInstanceResponse doGet(String url, otherargs...) {
       //some code...
       ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestHeader, String.class, requestMap);
       //another code...
    }
}

Here is the Test Class:

@RunWith(MockitoJUnitRunner.class)
public class SomeUtilTest {
    @Mock
    private RestTemplate restTemplate;

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

    @Test
    public void doGet() {
        OrderInstanceResponse exceptResponse = OrderInstanceResponse.builder().code("123").build();
        OrderInstanceRequest request = OrderInstanceRequest.builder().userId("123").build();

        Map<String, Object> testMap = new HashMap<>(1);
        testMap.put("userId", "123");

        Mockito.when(restTemplate.exchange(Mockito.anyString(), Mockito.any(), Mockito.any(), Mockito.eq(String.class), Mockito.eq(testMap)))
                .thenReturn(new ResponseEntity<>("\"code\":\"123\"", HttpStatus.OK));

        OrderInstanceResponse actualResponse = RestTemplateUtil.doGet("123", request, "123");
        Assert.assertEquals(actualResponse.getCode(), exceptResponse.getCode());
    }
}

There are some errors when I run this test: java.lang.IllegalArgumentException: URI is not absolute .

It seems that mock not work,There was a real request to "123".

How can i fix this bug?thanks

You need to pass a RestTemplate instance to the RestTemplateUtil as a dependency for this to work, rather than instantiating it in the doGet method. Then, in the unit test pass the mock RestTemplate instance to the RestTemplateUtil.

public class SomeUtil {
    public SomeUtil(RestTemplate restTemplate) { this.restTemplate = restTemplate }
    public OrderInstanceResponse doGet(String url, otherargs...) {
        ResponseEntity<String> responseEntity = this.restTemplate.exchange(...
    }
}

Or pass RestTemplate as a parameter if you want to keep it as a static method.

I found a solution. When we need to mock a object that created by new , like RestTemplate rest = new RestTemplate() , should be written like this:

PowerMockito.whenNew(ObjectToBeMocked.class).withAnyArguments().thenReturn(mockedObject);

Then add annotation @PrepareForTest({TheClassToBeTested.class}) . Please note, the param is the class that containing the object obtained by new . So, the complete code is as follows:

@RunWith(MockitoJUnitRunner.class)
@PrepareForTest({SomeUtil.class})
public class SomeUtilTest {

    @Mock
    private RestTemplate restTemplate;

    @Test
    public void doGet() {
        //......
        PowerMockito.whenNew(RestTemplate.class).withAnyArguments().thenReturn(restTemplate);
        //......
    }
}

Thanks all the friends who helped me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM