Spring 使用 Spock 模拟 Rest 模板
Spring Rest Template mocking with Spock
谁能给我举个例子,如何使用 Spock 测试 RestTemplate。
我的 类 看起来像这样:
@Service
public class SomeService {
@Autowired
private EndpointUrlProvider endpointUrlProvider;
private RestTemplate restTemplate = new RestTemplate();
public SomeResponse doSomePostRequest(HttpEntity<?> httpEntity) throws Exception {
ResponseEntity<SomeResponse> response;
try{
response = restTemplate.postForEntity(endpointUrlProvider.getSomeUrl(),httpEntity,SomeResponse.class);
} catch (Exception e){
throw new Exception("Exception occured during post for:" + httpEntity.getBody().getClass().getSimpleName() + " Cause: " + e.getMessage());
}
if(response.getStatusCode() == HttpStatus.OK){
return response.getBody();
}
throw new Exception("Error during " + response.getBody().getClass().getSimpleName() + "Http status is diffrent than 200: " + response.getBody().toString());
}
}
测试:
class SomeTest extends Specification {
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
@Autowired
SomeService someService
def "someTest"() {
when:
SomeResponse someResponse = someService.doSomePostRequest(new HttpEntity<>(new SomeBody(), new HttpHeaders()))
then:
someResponse == new SomeResponse()
}
}
主要问题是 RestTemplate 的模拟行为,我正在寻找如何以正确的方式做到这一点的解决方案。我不使用 spring 引导。
情况如下:
您在服务 class 中创建了新的 RestTemplate
。
private RestTemplate restTemplate = new RestTemplate();
然后您在测试中创建模拟并调用您的服务方法:
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
....
someService.doSomePostRequest
但是您的服务内部仍然有通常的休息模板。你应该注入模拟对象。我建议你通过构造函数来做。因此,将您的代码更改为:
@Service
public class SomeService {
private EndpointUrlProvider endpointUrlProvider;
private RestTemplate restTemplate;
@Autowired
public SomeService(EndpointUrlProvider endpointUrlProvider, RestTemplate restTemplate){
this.endpointUrlProvider = endpointUrlProvider;
this.restTemplate = restTemplate;
}
你的测试将是:
class SomeTest extends Specification {
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
SomeService someService = new SomeService ( null, restTemplate);
def "someTest"() {
when:
SomeResponse someResponse = someService.doSomePostRequest(new HttpEntity<>(new SomeBody(), new HttpHeaders()))
then:
someResponse == new SomeResponse()
}
}
现在您的服务对象将在注入的 MOCK 上调用方法,这不是通常的 RestTemplate
p.s.
spring.
认为构造函数注入是一种很好的做法
最好创建一个 RestTemplate bean 并将其注入到所有地方,而不是在所有服务中创建新对象。
谁能给我举个例子,如何使用 Spock 测试 RestTemplate。 我的 类 看起来像这样:
@Service
public class SomeService {
@Autowired
private EndpointUrlProvider endpointUrlProvider;
private RestTemplate restTemplate = new RestTemplate();
public SomeResponse doSomePostRequest(HttpEntity<?> httpEntity) throws Exception {
ResponseEntity<SomeResponse> response;
try{
response = restTemplate.postForEntity(endpointUrlProvider.getSomeUrl(),httpEntity,SomeResponse.class);
} catch (Exception e){
throw new Exception("Exception occured during post for:" + httpEntity.getBody().getClass().getSimpleName() + " Cause: " + e.getMessage());
}
if(response.getStatusCode() == HttpStatus.OK){
return response.getBody();
}
throw new Exception("Error during " + response.getBody().getClass().getSimpleName() + "Http status is diffrent than 200: " + response.getBody().toString());
}
}
测试:
class SomeTest extends Specification {
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
@Autowired
SomeService someService
def "someTest"() {
when:
SomeResponse someResponse = someService.doSomePostRequest(new HttpEntity<>(new SomeBody(), new HttpHeaders()))
then:
someResponse == new SomeResponse()
}
}
主要问题是 RestTemplate 的模拟行为,我正在寻找如何以正确的方式做到这一点的解决方案。我不使用 spring 引导。
情况如下:
您在服务 class 中创建了新的 RestTemplate
。
private RestTemplate restTemplate = new RestTemplate();
然后您在测试中创建模拟并调用您的服务方法:
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
....
someService.doSomePostRequest
但是您的服务内部仍然有通常的休息模板。你应该注入模拟对象。我建议你通过构造函数来做。因此,将您的代码更改为:
@Service
public class SomeService {
private EndpointUrlProvider endpointUrlProvider;
private RestTemplate restTemplate;
@Autowired
public SomeService(EndpointUrlProvider endpointUrlProvider, RestTemplate restTemplate){
this.endpointUrlProvider = endpointUrlProvider;
this.restTemplate = restTemplate;
}
你的测试将是:
class SomeTest extends Specification {
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
SomeService someService = new SomeService ( null, restTemplate);
def "someTest"() {
when:
SomeResponse someResponse = someService.doSomePostRequest(new HttpEntity<>(new SomeBody(), new HttpHeaders()))
then:
someResponse == new SomeResponse()
}
}
现在您的服务对象将在注入的 MOCK 上调用方法,这不是通常的 RestTemplate
p.s.
spring.
认为构造函数注入是一种很好的做法最好创建一个 RestTemplate bean 并将其注入到所有地方,而不是在所有服务中创建新对象。