如何在 Java Spring 中模拟 RestTemplate? [英] How to mock RestTemplate in Java Spring?

查看:27
本文介绍了如何在 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.看起来代码获得的是真实数据而不是模拟数据.任何人都可以帮我解决这个问题.

I tried to test a simple test for a service including a restclient. It looks I have not Mock the RestTemplate successfully. It looks like the code get the real data not the mock one. Anyone can help me with 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;
    }
}

推荐答案

问题是在您的 isEnabled 中,您正在创建一个新的 RestTemplate.这是错误的,原因有二,一是你不能模拟它,因为你正在创建一个新对象,二是避免每个请求创建新对象是好的.RestTemplate 是线程安全的,因此可以作为服务类成员,跨多个线程使用.

The problem is that in your isEnabled you 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.

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

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

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

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.

由于您在代码中使用了 InjectMock,我们可以使用它.

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

@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().你应该让 mockito 为你创建那些.通过使用 @Mock@Spy 对它们进行注释,您将确保 Mockito 会为您创建它们,更重要的是,会将模拟注入您的 服务对象.

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 @Mock and @Spy you will ensure that Mockito will create them for you, and more importantly, will inject the mocks into your service object.

这篇关于如何在 Java Spring 中模拟 RestTemplate?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆