简体   繁体   English

使用TestRestTemplate进行Spring集成测试

[英]Using TestRestTemplate for Spring Integration Testing

I am learning Spring Integration testing and using org.springframework.boot.test.web.client.TestRestTemplate . 我正在学习Spring Integration测试,并使用org.springframework.boot.test.web.client.TestRestTemplate My Spring Boot version is 2.0.2 and with some default configuration. 我的Spring Boot version is 2.0.2并且具有一些默认配置。

My Test class is : 我的测试班是:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class UserControllerIntegrationTest {

    @Autowired
    TestRestTemplate restTemplate;      

    String userBaseUrl = "/api/user/";

    UserDto userDto;

    @Before
    public void setUp() {

        EnhancedRandom er = EnhancedRandomBuilder.aNewEnhancedRandomBuilder().collectionSizeRange(1, 1).build();

        userDto = er.nextObject(UserDto.class);     

    }

    @Test
    public void registerUser() throws Exception{

        ResponseEntity<ServiceResponse> responseEntity = restTemplate.postForEntity(userBaseUrl+"register_user", userDto, ServiceResponse.class);
        assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
    }
    }

And controller endpoint method is : 控制器端点方法是:

@RequestMapping(value="register_user",method = RequestMethod.POST)  
    public ResponseEntity<ServiceResponse> registerUser(@RequestHeader HttpHeaders headers, @RequestBody UserDto userDto) {

        log.info("Register user");

        try {           
            ServiceResponse serviceResponse = new ServiceResponse("Users listed successfully"); 

            serviceResponse.setData(userService.registerUser(userDto));

            return new ResponseEntity<ServiceResponse>(serviceResponse,HttpStatus.OK);

        } catch (Exception e) {
            GeneralUtil.logError(log, "Error Occurred listing users", e);
            HttpHeaders httpHeaders = ServiceResponse.generateRuntimeErrors(e);
            return new ResponseEntity<>(httpHeaders, HttpStatus.EXPECTATION_FAILED);
        }
    }

And ServiceResponse is : 和ServiceResponse是:

public class ServiceResponse {

    private Boolean success;
    private String message;
    private Map<String, Object> params;
    private List<?> list;
    private Object data;
//getters,setters.
    }

This API endpoint works well when we test manually but doesn't work while running tests.It gives this error : 当我们进行手动测试时,此API端点运行良好,但在运行测试时却无法运行,并给出以下错误信息:

org.springframework.web.client.RestClientException: Error while extracting response for type [class com.eeposit.lattice.util.ServiceResponse] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.eeposit.lattice.util.ServiceResponse` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.eeposit.lattice.util.ServiceResponse` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (PushbackInputStream); line: 1, column: 2]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:115)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:991)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:974)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:725)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:680)
    at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:466)
    at org.springframework.boot.test.web.client.TestRestTemplate.postForEntity(TestRestTemplate.java:502)
    at com.eeposit.lattice.controller.UserControllerIntegrationTest.registerUser(UserControllerIntegrationTest.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.eeposit.lattice.util.ServiceResponse` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.eeposit.lattice.util.ServiceResponse` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (PushbackInputStream); line: 1, column: 2]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:100)
    ... 39 more
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.eeposit.lattice.util.ServiceResponse` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (PushbackInputStream); line: 1, column: 2]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1290)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
    ... 41 more

I tried to solve this issue googling but cannot fix the issue. 我试图通过谷歌搜索解决此问题,但无法解决该问题。

Your problem could be caused by that you get some error response which can't be parsed as ServiceResponse. 您的问题可能是由于您收到了一些错误响应,这些错误响应无法解析为ServiceResponse。 Try to change the ResponseEntity type to String instead of the ServiceResponse type. 尝试将ResponseEntity类型更改为String而不是ServiceResponse类型。

ResponseEntity<String> responseEntity = restTemplate.postForEntity(userBaseUrl+"register_user", userDto, String.class);
System.out.println("This is the response as a String" + responseEntity.getBody());

I believe that way you will be able to see what the call returns. 我相信这样您将能够看到电话返回的内容。

I solved this problem. 我解决了这个问题。 I did some modification in the code. 我在代码中做了一些修改。 I added this : 我添加了这个:

public HttpHeaders setHeaders(String accesstoken) {

        List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
        acceptableMediaTypes.add(MediaType.APPLICATION_JSON);

        HttpHeaders headers = new HttpHeaders();  
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(acceptableMediaTypes);
        headers.set("accesstoken", accesstoken);
        return headers;

    }

And changed the test method to this : 并将测试方法更改为:

@Test
    public void registerUser() throws Exception{

        super.getLog().info("Register user integration test.");

        HttpHeaders headers = setHeaders(null);
        HttpEntity<UserDto> entity = new HttpEntity<UserDto>(userDto,headers);

        ResponseEntity<String> responseEntity = restTemplate.exchange(userBaseUrl+"register_user", HttpMethod.POST, entity, String.class);  

        assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
        assertNotNull(responseEntity.getBody());    

        ServiceResponse serviceResponse = super.gson.fromJson(responseEntity.getBody(), ServiceResponse.class);     

        Map<String, Object> data = (Map<String, Object>) serviceResponse.getData();

        assertTrue(data.containsKey("accesstoken"));

        assertTrue(data.containsKey("user"));
    }

Instead of using this : 而不是使用这个:

ResponseEntity<ServiceResponse> responseEntity = restTemplate.postForEntity(userBaseUrl+"register_user", userDto, ServiceResponse.class);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM