如何在 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
How to mock RestTemplate in Java Spring?
提问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 RestTemplate
successfully. 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 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.
问题是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 @Mock
and @Spy
you will ensure that Mockito will create them for you, and more importantly, will inject the mocks into your service
object.
请注意,我做了一些更改。首先,我删除了new RestTemplate()
和new Service()
。你应该让 mockito 为你创建那些。通过使用@Mock
and注释它们,@Spy
您将确保 Mockito 会为您创建它们,更重要的是,会将模拟注入到您的service
对象中。
回答by Keith
Spring MVC's test framework has offered the class MockRestServiceServer
for 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 来自动创建对象。