如何在Java Spring中模拟RestTemplate?


问题内容
public class ServiceTest {
    @Mock
    RestTemplate restTemplate = new RestTemplate();
    @InjectMocks
    Service service = new Service();
    ResponseEntity responseEntity = mock(ResponseEntity.class);

    @Test
    public void test() throws Exception {
        Mockito.when(restTemplate.getForEntity(
                Mockito.anyString(),
                Matchers.any(Class.class)
                ))
                .thenReturn(responseEntity);
        boolean res = service.isEnabled("something");
        Assert.assertEquals(res, false);
    }

我尝试对包含restclient的服务进行简单测试。看来我还没有RestTemplate成功模拟。看起来代码获得的是真实数据,而不是模拟数据。任何人都可以帮助我。

服务本身将如下所示:

public class Service{
    public boolean isEnabled(String xxx) {
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
        if(...)return true;
        return false;
    }
}

问题答案:

问题是isEnabled您正在创建一个新的RestTemplate。这是错误的,有两个原因,其一是由于您正在创建新对象而无法模拟它,其二最好避免每个请求都创建新对象。RestTemplate是线程安全的,因此可以是服务类成员,可以在许多线程中使用。

将您的服务类别更改为以下内容:

public class Service{

    RestTemplate restTemplate = new RestTemplate();

    public boolean isEnabled(String xxx) {
        ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
        if(...)return true;
        return false;
    }
}

现在您的RestTemplate已成为类成员,您现在可以通过以下两种方法之一正确地进行模拟。一种,使用@InjectMock或使用您从测试中调用的setter方法进行注入。

由于您在代码中使用InjectMock,因此我们可以使用它。

@RunWith(MockitoJUnitRunner.class) 
public class ServiceTest {
    @Mock
    RestTemplate restTemplate;
    @InjectMocks
    @Spy
    Service service;
    ResponseEntity responseEntity = mock(ResponseEntity.class);

    @Test
    public void test() throws Exception {
        Mockito.when(restTemplate.getForEntity(
                Mockito.anyString(),
                ArgumentMatchers.any(Class.class)
                ))
                .thenReturn(responseEntity);
        boolean res = service.isEnabled("something");
        Assert.assertEquals(res, false);
    }

注意,我做了一些更改。首先,我删除了new RestTemplate()new Service()。您应该让模仿者为您创建那些。通过给它们添加注释@Mock@Spy您将确保Mockito将为您创建它们,更重要的是,将模拟插入到您的service对象中。