如何在 Java Spring 中模拟 RestTemplate?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42406625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:08:19  来源:igfitidea点击:

How to mock RestTemplate in Java Spring?

javaunit-testingspring-mvcmockito

提问by c2340878

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);
    }

I tried to test a simple test for a service including a restclient. It looks I have not Mock the RestTemplatesuccessfully. It looks like the code get the real data not the mock one. Anyone can help me with this.

我试图测试一个包括 restclient 的服务的简单测试。看起来我没有RestTemplate成功模拟。看起来代码获得的是真实数据而不是模拟数据。任何人都可以帮助我解决这个问题。

The service itself will looks as this:

服务本身将如下所示:

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;
    }
}

采纳答案by Jose Martinez

The problem is that in your isEnabledyou are creating a new RestTemplate. This is wrong for two reasons, one is that you cannot mock it since you are creating a new one, and second it is good to avoid creating new objects per request. RestTemplate is thread safe and hence can be a service class member, being used across many threads.

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

Change your service class to something like this:

将您的服务类更改为如下所示:

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;
    }
}

Now that your RestTemplate has become a class member you can now properly mock through one of two ways. One, inject it using the @InjectMock, or use a setter method that you call from your test.

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

Since you are using InjectMock in your code we can go with that.

由于您在代码中使用了 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);
    }

Notice that I made a few changes. First, I removed the new RestTemplate()and new Service(). You should let mockito create those for you. By annotating them with @Mockand @Spyyou will ensure that Mockito will create them for you, and more importantly, will inject the mocks into your serviceobject.

请注意,我做了一些更改。首先,我删除了new RestTemplate()new Service()。你应该让 mockito 为你创建那些。通过使用@Mockand注释它们,@Spy您将确保 Mockito 会为您创建它们,更重要的是,会将模拟注入到您的service对象中。

回答by Keith

Spring MVC's test framework has offered the class MockRestServiceServerfor unit testing RESTful service code.

Spring MVC 的测试框架提供了MockRestServiceServer用于单元测试 RESTful 服务代码的类。

Here is a tutorialon its use.

这是有关其使用的教程

回答by hiroyukik

If you use @Autowired, you could use MockRestServiceServer. The below is the sample.

如果您使用@Autowired,则可以使用 MockRestServiceServer。下面是示例。

@Service
public class Service{
    @Autowired
    private RestTemplate restTemplate;

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

@Service needs to use @Autowired for creating object automatically.

@Service 需要使用@Autowired 来自动创建对象。