Java 如何模拟REST模板交换?
我有一项服务,我需要通过rest向外部服务器询问一些信息:Java 如何模拟REST模板交换?,java,spring-boot,junit,mockito,Java,Spring Boot,Junit,Mockito,我有一项服务,我需要通过rest向外部服务器询问一些信息: public class SomeService { public List<ObjectA> getListofObjectsA() { List<ObjectA> objectAList = new ArrayList<ObjectA>(); ParameterizedTypeReference<List<ObjectA>> typ
public class SomeService {
public List<ObjectA> getListofObjectsA() {
List<ObjectA> objectAList = new ArrayList<ObjectA>();
ParameterizedTypeReference<List<ObjectA>> typeRef = new ParameterizedTypeReference<List<ObjectA>>() {};
ResponseEntity<List<ObjectA>> responseEntity = restTemplate.exchange("/objects/get-objectA", HttpMethod.POST, new HttpEntity<>(ObjectAList), typeRef);
return responseEntity.getBody();
}
}
但是,上面的代码不起作用,它显示
responseEntity
为null
。如何更正测试以正确模拟restemplate.exchange
?您不需要MockRestServiceServer
对象。注释是@InjectMocks
而不是@Inject
。下面是一个应该可以工作的示例代码
@RunWith(MockitoJUnitRunner.class)
public class SomeServiceTest {
@Mock
private RestTemplate restTemplate;
@InjectMocks
private SomeService underTest;
@Test
public void testGetObjectAList() {
ObjectA myobjectA = new ObjectA();
//define the entity you want the exchange to return
ResponseEntity<List<ObjectA>> myEntity = new ResponseEntity<List<ObjectA>>(HttpStatus.ACCEPTED);
Mockito.when(restTemplate.exchange(
Matchers.eq("/objects/get-objectA"),
Matchers.eq(HttpMethod.POST),
Matchers.<HttpEntity<List<ObjectA>>>any(),
Matchers.<ParameterizedTypeReference<List<ObjectA>>>any())
).thenReturn(myEntity);
List<ObjectA> res = underTest.getListofObjectsA();
Assert.assertEquals(myobjectA, res.get(0));
}
@RunWith(MockitoJUnitRunner.class)
公共类服务测试{
@嘲弄
私有RestTemplate RestTemplate;
@注射模拟
私人服务测试不足;
@试验
public void testGetObjectAList(){
ObjectA myobjectA=新ObjectA();
//定义希望exchange返回的实体
ResponseEntity myEntity=新的ResponseEntity(HttpStatus.ACCEPTED);
Mockito.when(restemplate.exchange(
Matchers.eq(“/objects/get objectA”),
Matchers.eq(HttpMethod.POST),
Matchers.any(),
Matchers.any())
).然后返回(myEntity);
List res=underTest.getListofObjectsA();
Assert.assertEquals(myobjectA,res.get(0));
}
ResponseEntity ResponseEntity=新的ResponseEntity(“sampleBodyString”,HttpStatus.ACCEPTED);
何时(restemplate.exchange)(
Matchers.anyString(),
Matchers.any(HttpMethod.class),
Matchers.对我来说,我必须使用Matchers.any(URI.class)
Mockito.when(restemplate.exchange(Matchers.any(URI.class))和Matchers.any(HttpMethod.class),Matchers.我实现了一个非常有用的工具。它提供了一个可以接收一些上下文的clienthtprequestfactory
。通过这样做,它可以检查所有客户端层,例如检查查询参数是否有值,是否设置了头,以及检查反序列化是否工作正常。如果您打算在没有c的情况下测试服务关于rest调用,我建议不要在单元测试中使用任何注释来简化测试
因此,我的建议是重构您的服务,使用注入构造函数接收resttemplate。这将促进测试。示例:
@Service
class SomeService {
@AutoWired
SomeService(TestTemplateObjects restTemplateObjects) {
this.restTemplateObjects = restTemplateObjects;
}
}
RestTemplate作为组件,将在以下时间之后注入和模拟:
@Component
public class RestTemplateObjects {
private final RestTemplate restTemplate;
public RestTemplateObjects () {
this.restTemplate = new RestTemplate();
// you can add extra setup the restTemplate here, like errorHandler or converters
}
public RestTemplate getRestTemplate() {
return restTemplate;
}
}
以及测试:
public void test() {
when(mockedRestTemplateObject.get).thenReturn(mockRestTemplate);
//mock restTemplate.exchange
when(mockRestTemplate.exchange(...)).thenReturn(mockedResponseEntity);
SomeService someService = new SomeService(mockedRestTemplateObject);
someService.getListofObjectsA();
}
通过这种方式,您可以通过SomeService构造函数直接访问模拟rest模板。这是我的工作
ResourceBean resourceBean = initResourceBean();
ResponseEntity<ResourceBean> responseEntity
= new ResponseEntity<ResourceBean>(resourceBean, HttpStatus.ACCEPTED);
when(restTemplate.exchange(
Matchers.anyObject(),
Matchers.any(HttpMethod.class),
Matchers.<HttpEntity> any(),
Matchers.<Class<ResourceBean>> any())
).thenReturn(responseEntity);
ResourceBean ResourceBean=initResourceBean();
响应响应响应响应响应响应
=新响应属性(resourceBean,HttpStatus.ACCEPTED);
何时(restemplate.exchange)(
Matchers.anyObject(),
Matchers.any(HttpMethod.class),
Matchers.any(),
Matchers.any())
).然后返回(响应性);
这是一个非弃用类的示例
when(restemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.any())
.然后返回(响应性);
RestTemplate
实例必须是真实对象。如果您创建了RestTemplate
的真实实例并使其成为@Spy
,则该实例应该可以工作
@Spy
private RestTemplate restTemplate = new RestTemplate();
如果您使用的是restemplatebuilder
,则通常无法正常工作。您需要在测试类中添加此选项以及when(条件)
假设您有一个交换电话,如下所示:
String url = "/zzz/{accountNumber}";
Optional<AccountResponse> accResponse = Optional.ofNullable(accountNumber)
.map(account -> {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "bearer 121212");
HttpEntity<Object> entity = new HttpEntity<>(headers);
ResponseEntity<AccountResponse> response = template.exchange(
url,
GET,
entity,
AccountResponse.class,
accountNumber
);
return response.getBody();
});
stringurl=“/zzz/{accountNumber}”;
可选的注册响应=可选的可注册数量(accountNumber)
.map(帐户->{
HttpHeaders=新的HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
标题集(“授权”、“持有人121212”);
HttpEntity=新的HttpEntity(标题);
ResponseEntity response=template.exchange(
网址,
得到,
实体,
AccountResponse.class,
帐号
);
返回response.getBody();
});
要在测试用例中模拟这一点,您可以使用mocitko,如下所示:
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<AccountResponse>>any(),
ArgumentMatchers.<ParameterizedTypeReference<List<Object>>>any())
)
when(restemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.any(),
ArgumentMatchers.any())
)
我曾经遇到过这样的错误。我找到了一个更可靠的解决方案。我也提到了对我有效的导入语句。下面的代码完全模拟了重新模板
导入org.mockito.Matchers;
导入静态org.mockito.Matchers.any
HttpHeaders headers = new Headers();
headers.setExpires(10000L);
ResponseEntity<String> responseEntity = new ResponseEntity<>("dummyString", headers, HttpStatus.OK);
when(restTemplate.exchange( Matchers.anyString(),
Matchers.any(HttpMethod.class),
Matchers.<HttpEntity<?>> any(),
Matchers.<Class<String>> any())).thenReturn(responseEntity);
HttpHeaders=newheaders();
标题。设置过期(10000L);
ResponseEntity ResponseEntity=新的ResponseEntity(“dummyString”,标题,HttpStatus.OK);
当(restTemplate.exchange)(Matchers.anyString()),
Matchers.any(HttpMethod.class),
Matchers.如果有人仍然面临这个问题,Captor annotation为我工作
@Captor
private ArgumentCaptor<Object> argumentCaptor;
@Captor
私人辩手辩手;
然后我可以通过以下方式模拟请求:
ResponseEntity<YourTestResponse> testEntity = new ResponseEntity<>(
getTestFactoryResponse(),
HttpStatus.OK);
when(mockRestTemplate.exchange((String) argumentCaptor.capture(),
(HttpMethod) argumentCaptor.capture(),
(HttpEntity<?>) argumentCaptor.capture(),
(Class<YourTestResponse.class>) any())
).thenReturn(testEntity);
ResponseEntity testEntity=新的ResponseEntity(
getTestFactoryResponse(),
HttpStatus.OK);
当(mockrestemplate.exchange((字符串)argumentCaptor.capture()时,
(HttpMethod)argumentCaptor.capture(),
(HttpEntity)argumentCaptor.capture(),
(类)any())
).然后返回(测试实体);
如果有人在尝试模拟restTemplate.exchange(…)时遇到此问题,则问题似乎出在matchers上。例如:以下操作不起作用
when(ecocashRestTemplate.exchange(Mockito.any()
, Mockito.eq(HttpMethod.GET)
, Mockito.any(HttpEntity.class)
, Mockito.<Class<UserTransaction>>any())
).thenReturn(new ResponseEntity<>(transaction, HttpStatus.OK));
when(ecocashRestTemplate.exchange(Mockito.any)()
,Mockito.eq(HttpMethod.GET)
,Mockito.any(HttpEntity.class)
,Mockito.any())
).然后返回(新的响应属性(事务,HttpStatus.OK));
但这一条确实有效:
ResponseEntity<UserTransaction> variable = new ResponseEntity<>(transaction, HttpStatus.OK);
when(ecocashRestTemplate.exchange(Mockito.anyString()
, Mockito.eq(HttpMethod.GET)
, Mockito.any(HttpEntity.class)
, Mockito.<Class<UserTransaction>>any())
).thenReturn(new ResponseEntity<>(transaction, HttpStatus.OK));
Re
HttpHeaders headers = new Headers();
headers.setExpires(10000L);
ResponseEntity<String> responseEntity = new ResponseEntity<>("dummyString", headers, HttpStatus.OK);
when(restTemplate.exchange( Matchers.anyString(),
Matchers.any(HttpMethod.class),
Matchers.<HttpEntity<?>> any(),
Matchers.<Class<String>> any())).thenReturn(responseEntity);
@Captor
private ArgumentCaptor<Object> argumentCaptor;
ResponseEntity<YourTestResponse> testEntity = new ResponseEntity<>(
getTestFactoryResponse(),
HttpStatus.OK);
when(mockRestTemplate.exchange((String) argumentCaptor.capture(),
(HttpMethod) argumentCaptor.capture(),
(HttpEntity<?>) argumentCaptor.capture(),
(Class<YourTestResponse.class>) any())
).thenReturn(testEntity);
when(ecocashRestTemplate.exchange(Mockito.any()
, Mockito.eq(HttpMethod.GET)
, Mockito.any(HttpEntity.class)
, Mockito.<Class<UserTransaction>>any())
).thenReturn(new ResponseEntity<>(transaction, HttpStatus.OK));
ResponseEntity<UserTransaction> variable = new ResponseEntity<>(transaction, HttpStatus.OK);
when(ecocashRestTemplate.exchange(Mockito.anyString()
, Mockito.eq(HttpMethod.GET)
, Mockito.any(HttpEntity.class)
, Mockito.<Class<UserTransaction>>any())
).thenReturn(new ResponseEntity<>(transaction, HttpStatus.OK));