亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Spring MVC測試框架詳解——客戶端測試

系統 1818 0

對于客戶端測試以前經常使用的方法是啟動一個內嵌的jetty/tomcat容器,然后發送真實的請求到相應的控制器;這種方式的缺點就是速度慢;自Spring 3.2開始提供了對RestTemplate的模擬服務器測試方式,也就是說使用RestTemplate測試時無須啟動服務器,而是模擬一個服務器進行測試,這樣的話速度是非??斓摹?

?

2 RestTemplate客戶端測試

整個環境在上一篇《 Spring MVC測試框架詳解——服務端測試 》基礎上進行構建。

?

UserRestController控制器

Java代碼?? 收藏代碼
  1. @RestController ??
  2. @RequestMapping ( "/users" )??
  3. public ? class ?UserRestController?{??
  4. ??
  5. ???? private ?UserService?userService;??
  6. ??
  7. ???? @Autowired ??
  8. ???? public ?UserRestController(UserService?userService)?{??
  9. ???????? this .userService?=?userService;??
  10. ????}??
  11. ??
  12. ???? @RequestMapping (value?=? "/{id}" ,?method?=?RequestMethod.GET,?produces?=?MediaType.APPLICATION_JSON_VALUE)??
  13. ???? public ?User?findById( @PathVariable ( "id" )?Long?id)?{??
  14. ???????? return ?userService.findById(1L);??
  15. ????}??
  16. ??
  17. ???? @RequestMapping (method?=?RequestMethod.POST)??
  18. ???? public ?ResponseEntity<User>?save( @RequestBody ?User?user,?UriComponentsBuilder?uriComponentsBuilder)?{??
  19. ???????? //save?user ??
  20. ????????user.setId(1L);??
  21. ????????MultiValueMap?headers?=? new ?HttpHeaders();??
  22. ????????headers.set( "Location" ,?uriComponentsBuilder.path( "/users/{id}" ).buildAndExpand(user.getId()).toUriString());??
  23. ???????? return ? new ?ResponseEntity(user,?headers,?HttpStatus.CREATED);??
  24. ????}??
  25. ??
  26. ???? @RequestMapping (value?=? "/{id}" ,?method?=?RequestMethod.PUT,?consumes?=?MediaType.APPLICATION_JSON_VALUE)??
  27. ???? @ResponseStatus (HttpStatus.NO_CONTENT)??
  28. ???? public ? void ?update( @RequestBody ?User?user)?{??
  29. ???????? //update?by?id ??
  30. ????}??
  31. ??
  32. ???? @RequestMapping (value?=? "/{id}" ,?method?=?RequestMethod.DELETE)??
  33. ???? public ? void ?delete( @PathVariable ( "id" )?Long?id)?{??
  34. ???????? //delete?by?id ??
  35. ????}??
  36. }??

?

UserService

Java代碼?? 收藏代碼
  1. package ?com.sishuok.mvc.service;??
  2. ??
  3. import ?com.sishuok.mvc.entity.User;??
  4. ??
  5. public ? interface ?UserService?{??
  6. ???? public ?User?findById(Long?id);??
  7. }??
?

UserServiceImpl

Java代碼?? 收藏代碼
  1. package ?com.sishuok.mvc.service;??
  2. ??
  3. import ?com.sishuok.mvc.entity.User;??
  4. import ?org.springframework.stereotype.Service;??
  5. ??
  6. @Service ??
  7. public ? class ?UserServiceImpl? implements ?UserService?{??
  8. ??
  9. ???? public ?User?findById(Long?id)?{??
  10. ????????User?user?=? new ?User();??
  11. ????????user.setId(id);??
  12. ????????user.setName( "zhang" );??
  13. ???????? return ?user;??
  14. ????}??
  15. }??
?

AbstractClientTest測試基類

Java代碼?? 收藏代碼
  1. public ? abstract ? class ?AbstractClientTest?{??
  2. ??
  3. ???? static ?RestTemplate?restTemplate;??
  4. ????ObjectMapper?objectMapper;? //JSON ??
  5. ????Jaxb2Marshaller?marshaller;? //XML ??
  6. ????String?baseUri?=? "http://localhost:8080/users" ;??
  7. ??
  8. ???? @Before ??
  9. ???? public ? void ?setUp()? throws ?Exception?{??
  10. ????????objectMapper?=? new ?ObjectMapper();? //需要添加jackson?jar包 ??
  11. ??
  12. ????????marshaller?=? new ?Jaxb2Marshaller();? //需要添加jaxb2實現(如xstream) ??
  13. ????????marshaller.setPackagesToScan( new ?String[]?{ "com.sishuok" });??
  14. ????????marshaller.afterPropertiesSet();??
  15. ??
  16. ????????restTemplate?=? new ?RestTemplate();??
  17. ????}??
  18. }??
??

?

2.1 使用內嵌Jetty方式啟動容器進行

需要添加jetty依賴:

Java代碼?? 收藏代碼
  1. <dependency>??
  2. ????<groupId>org.eclipse.jetty</groupId>??
  3. ????<artifactId>jetty-server</artifactId>??
  4. ????<version>${jetty.version}</version>??
  5. ????<scope>test</scope>??
  6. </dependency>??
  7. <dependency>??
  8. ????<groupId>org.eclipse.jetty</groupId>??
  9. ????<artifactId>jetty-webapp</artifactId>??
  10. ????<version>${jetty.version}</version>??
  11. ????<scope>test</scope>??
  12. </dependency>??

?

如果要測試JSP,請添加

Java代碼?? 收藏代碼
  1. <dependency>??
  2. ????<groupId>org.eclipse.jetty</groupId>??
  3. ????<artifactId>jetty-jsp</artifactId>??
  4. ????<version>${jetty.version}</version>??
  5. ????<scope>test</scope>??
  6. </dependency>??

版本:<jetty.version>8.1.8.v20121106</jetty.version>

?

?

測試示例( EmbeddedJettyClientTest.java )

Java代碼?? 收藏代碼
  1. public ? class ?EmbeddedJettyClientTest? extends ?AbstractClientTest?{??
  2. ??
  3. ???? private ? static ?Server?server;??
  4. ??
  5. ???? @BeforeClass ??
  6. ???? public ? static ? void ?beforeClass()? throws ?Exception?{??
  7. ???????? //創建一個server ??
  8. ????????server?=? new ?Server( 8080 );??
  9. ????????WebAppContext?context?=? new ?WebAppContext();??
  10. ????????String?webapp?=? "spring-mvc-test/src/main/webapp" ;??
  11. ????????context.setDescriptor(webapp?+? "/WEB-INF/web.xml" );?? //指定web.xml配置文件 ??
  12. ????????context.setResourceBase(webapp);?? //指定webapp目錄 ??
  13. ????????context.setContextPath( "/" );??
  14. ????????context.setParentLoaderPriority( true );??
  15. ??
  16. ????????server.setHandler(context);??
  17. ????????server.start();??
  18. ????}??
  19. ??
  20. ???? @AfterClass ??
  21. ???? public ? static ? void ?afterClass()? throws ?Exception?{??
  22. ????????server.stop();? //當測試結束時停止服務器 ??
  23. ????}??
  24. ??
  25. ???? @Test ??
  26. ???? public ? void ?testFindById()? throws ?Exception?{??
  27. ????????ResponseEntity<User>?entity?=?restTemplate.getForEntity(baseUri?+? "/{id}" ,?User. class ,?1L);??
  28. ??
  29. ????????assertEquals(HttpStatus.OK,?entity.getStatusCode());??
  30. ????????assertThat(entity.getHeaders().getContentType().toString(),?containsString(MediaType.APPLICATION_JSON_VALUE));??
  31. ????????assertThat(entity.getBody(),?hasProperty( "name" ,?is( "zhang" )));??
  32. ????}??
  33. ???? //省略其他,請參考github ??
  34. }??
?

?

此處通過內嵌Jetty啟動一個web容器,然后使用RestTemplate訪問真實的uri進行訪問,然后進行斷言驗證。

?

這種方式的最大的缺點是如果我只測試UserRestController,其他的組件也會加載,屬于集成測試,速度非常慢。伴隨著Spring Boot項目的發布,我們可以使用Spring Boot進行測試。

?

2.2 使用Spring Boot進行測試

spring boot請參考 spring boot官網 ?和《 Spring Boot——2分鐘構建spring web mvc REST風格HelloWorld 》進行入門。通過spring boot我們可以只加載某個控制器進行測試。更加方便。

?

添加spring-boot-starter-web依賴:

Java代碼?? 收藏代碼
  1. <dependency>??
  2. ????<groupId>org.springframework.boot</groupId>??
  3. ????<artifactId>spring-boot-starter-web</artifactId>??
  4. ????<version>${spring.boot.version}</version>??
  5. ????<scope>test</scope>??
  6. </dependency>??

版本:<spring.boot.version>0.5.0.BUILD-SNAPSHOT</spring.boot.version>,目前還處于SNAPSHOT版本。

?

?

測試示例( SpringBootClientTest.java )

Java代碼?? 收藏代碼
  1. public ? class ?SpringBootClientTest? extends ?AbstractClientTest?{??
  2. ??
  3. ???? private ? static ?ApplicationContext?ctx;??
  4. ??
  5. ???? @BeforeClass ??
  6. ???? public ? static ? void ?beforeClass()? throws ?Exception?{??
  7. ????????ctx?=?SpringApplication.run(Config. class );? //啟動服務器?加載Config指定的組件 ??
  8. ????}??
  9. ??
  10. ???? @AfterClass ??
  11. ???? public ? static ? void ?afterClass()? throws ?Exception?{??
  12. ????????SpringApplication.exit(ctx); //退出服務器 ??
  13. ????}??
  14. ??
  15. ??
  16. ???? @Test ??
  17. ???? public ? void ?testFindById()? throws ?Exception?{??
  18. ????????ResponseEntity<User>?entity?=?restTemplate.getForEntity(baseUri?+? "/{id}" ,?User. class ,?1L);??
  19. ??
  20. ????????assertEquals(HttpStatus.OK,?entity.getStatusCode());??
  21. ????????assertThat(entity.getHeaders().getContentType().toString(),?containsString(MediaType.APPLICATION_JSON_VALUE));??
  22. ????????assertThat(entity.getBody(),?hasProperty( "name" ,?is( "zhang" )));??
  23. ????}??
  24. ??
  25. ???? //省略其他,請參考github ??
  26. ?????
  27. ???? @Configuration ??
  28. ???? @EnableAutoConfiguration ??
  29. ???? static ? class ?Config?{??
  30. ??
  31. ???????? @Bean ??
  32. ???????? public ?EmbeddedServletContainerFactory?servletContainer()?{??
  33. ???????????? return ? new ?JettyEmbeddedServletContainerFactory();??
  34. ????????}??
  35. ??
  36. ???????? @Bean ??
  37. ???????? public ?UserRestController?userController()?{??
  38. ???????????? return ? new ?UserRestController(userService());??
  39. ????????}??
  40. ??
  41. ???????? @Bean ??
  42. ???????? public ?UserService?userService()?{??
  43. ???????????? //Mockito請參考?http://stamen.iteye.com/blog/1470066 ??
  44. ????????????UserService?userService?=?Mockito.mock(UserService. class );??
  45. ????????????User?user?=? new ?User();??
  46. ????????????user.setId(1L);??
  47. ????????????user.setName( "zhang" );??
  48. ????????????Mockito.when(userService.findById(Mockito.any(Long. class ))).thenReturn(user);??
  49. ???????????? return ?userService;??
  50. //????????????return?new?UserServiceImpl();?//此處也可以返回真實的UserService實現 ??
  51. ????????}??
  52. ????}??
  53. ??
  54. }??

?

通過SpringApplication.run啟動一個服務器,然后Config.xml是Spring的Java配置方式,此處只加載了UserRestController及其依賴UserService,對于UserService可以通過如Mockito進行模擬/也可以注入真實的實現,Mockito請參考《 單元測試系列之2:模擬利器Mockito 》。可以通過EmbeddedServletContainerFactory子類指定使用哪個內嵌的web容器(目前支持:jetty/tomcat)。

?

這種方式的優點就是速度比內嵌Jetty容器速度快,但是還是不夠快且還需要啟動一個服務器(開一個端口),因此Spring 3.2提供了模擬Server的方式進行測試。即服務器是通過Mock技術模擬的而不是真的啟動一個服務器。

?

上述兩種方式對于如果服務還不存在的情況也是無法測試的,因此Mock Server進行測試時最好的選擇。

?

2.3 使用Mock Service Server進行測試

通過Mock Service Server方式的優點:

不需要啟動服務器;

可以在服務還沒寫好的情況下進行測試,這樣可以進行并行開發/測試。

?

對于Mock Service Server主要操作步驟:

1、通過MockRestServiceServer創建RestTemplate的Mock Server;

2、添加客戶端請求斷言,即用于判斷客戶端請求的斷言;

3、添加服務端響應,即返回給客戶端的響應;

?

為了方便測試,請靜態導入:

Java代碼?? 收藏代碼
  1. import ? static ?org.springframework.test.web.client.*;??
  2. import ? static ?org.springframework.test.web.client.match.MockRestRequestMatchers.*;??
  3. import ? static ?org.springframework.test.web.client.response.MockRestResponseCreators.*;??

?

測試示例( MockServerClientTest.java )

Java代碼?? 收藏代碼
  1. public ? class ?MockServerClientTest? extends ?AbstractClientTest?{??
  2. ??
  3. ???? private ?MockRestServiceServer?mockServer;??
  4. ??
  5. ???? @Before ??
  6. ???? public ? void ?setUp()? throws ?Exception?{??
  7. ???????? super .setUp();??
  8. ???????? //模擬一個服務器 ??
  9. ????????mockServer?=?createServer(restTemplate);??
  10. ????}??
  11. ??
  12. ???? @Test ??
  13. ???? public ? void ?testFindById()? throws ?JsonProcessingException?{??
  14. ????????String?uri?=?baseUri?+? "/{id}" ;??
  15. ????????Long?id?=?1L;??
  16. ????????User?user?=? new ?User();??
  17. ????????user.setId(1L);??
  18. ????????user.setName( "zhang" );??
  19. ????????String?userJson?=?objectMapper.writeValueAsString(user);??
  20. ????????String?requestUri?=?UriComponentsBuilder.fromUriString(uri).buildAndExpand(id).toUriString();??
  21. ??
  22. ???????? //添加服務器端斷言 ??
  23. ????????mockServer??
  24. ????????????????.expect(requestTo(requestUri))??
  25. ????????????????.andExpect(method(HttpMethod.GET))??
  26. ????????????????.andRespond(withSuccess(userJson,?MediaType.APPLICATION_JSON));??
  27. ??
  28. ???????? //2、訪問URI(與API交互) ??
  29. ????????ResponseEntity<User>?entity?=?restTemplate.getForEntity(uri,?User. class ,?id);??
  30. ??
  31. ???????? //3.1、客戶端驗證 ??
  32. ????????assertEquals(HttpStatus.OK,?entity.getStatusCode());??
  33. ????????assertThat(entity.getHeaders().getContentType().toString(),?containsString(MediaType.APPLICATION_JSON_VALUE));??
  34. ????????assertThat(entity.getBody(),?hasProperty( "name" ,?is( "zhang" )));??
  35. ??
  36. ???????? //3.2、服務器端驗證(驗證之前添加的服務器端斷言) ??
  37. ????????mockServer.verify();??
  38. ????}??
  39. ???? //省略其他,請參考github ??
  40. }??

??

測試步驟:

1、準備測試環境

首先創建RestTemplate,然后通過MockRestServiceServer.createServer(restTemplate)創建一個Mock Server,其會自動設置restTemplate的requestFactory為RequestMatcherClientHttpRequestFactory(restTemplate發送請求時都通過ClientHttpRequestFactory創建ClientHttpRequest)。

2、調用API

即restTemplate.getForEntity(uri, User.class, id)訪問rest web service;

3、斷言驗證

3.1、客戶端請求斷言驗證

如mockServer.expect(requestTo(requestUri)).andExpect(method(HttpMethod.GET)):即會驗證之后通過restTemplate發送請求的uri是requestUri,且請求方法是GET;

3.2、服務端響應斷言驗證

首先通過mockServer.andRespond(withSuccess(new ObjectMapper().writeValueAsString(user), MediaType.APPLICATION_JSON));返回給客戶端響應信息;

然后restTemplate就可以得到ResponseEntity,之后就可以通過斷言進行驗證了;

4、 卸載測試環境

?

對于單元測試步驟請參考: 加速Java應用開發速度3——單元/集成測試+CI

?

2.4 了解測試API

?

MockRestServiceServer

用來創建模擬服務器,其提供了createServer(RestTemplate restTemplate),傳入一個restTemplate即可創建一個MockRestServiceServer;在createServer中:

Java代碼?? 收藏代碼
  1. MockRestServiceServer?mockServer?=? new ?MockRestServiceServer();??
  2. RequestMatcherClientHttpRequestFactory?factory?=?mockServer. new ?RequestMatcherClientHttpRequestFactory();??
  3. ??
  4. restTemplate.setRequestFactory(factory);??
即模擬一個ClientHttpRequestFactory,然后設置回RestTemplate,這樣所有發送的請求都會到這個MockRestServiceServer。拿到MockRestServiceServer后,接著就需要添加請求斷言和返回響應,然后進行驗證。

?

?

RequestMatcher/MockRestRequestMatchers

RequestMatcher用于驗證請求信息的驗證器,即RestTemplate發送的請求的URI、請求方法、請求的Body體內容等等;spring mvc測試框架提供了很多***RequestMatchers來滿足測試需求;類似于《Spring MVC測試框架詳解——服務端測試》中的***ResultMatchers;注意這些***RequestMatchers并不是ResultMatcher的子類,而是返回RequestMatcher實例的。Spring mvc測試框架為了測試方便提供了MockRestRequestMatchers靜態工廠方法方便操作;具體的API如下:

RequestMatcher anything():即請求可以是任何東西;

RequestMatcher requestTo(final Matcher<String> matcher)/RequestMatcher requestTo(final String expectedUri)/RequestMatcher requestTo(final URI uri):請求URI必須匹配某個Matcher/uri字符串/URI;

RequestMatcher method(final HttpMethod method):請求方法必須匹配某個請求方法;

RequestMatcher header(final String name, final Matcher<? super String>... matchers)/RequestMatcher header(final String name, final String... expectedValues):請求頭必須匹配某個Matcher/某些值;

ContentRequestMatchers content():獲取內容匹配器,然后可以通過如contentType(String expectedContentType)進行ContentType匹配等,具體請參考javadoc;

JsonPathRequestMatchers jsonPath(String expression, Object ... args)/RequestMatcher jsonPath(String expression, Matcher<T> matcher):獲取Json路徑匹配器/直接進行路徑匹配,具體請參考javadoc;

XpathRequestMatchers xpath(String expression, Object... args)/XpathRequestMatchers xpath(String expression, Map<String, String> namespaces, Object... args):獲取Xpath表達式匹配器/直接進行Xpath表達式匹配,具體請參考javadoc;

?

ResponseCreator/MockRestResponseCreators

ResponseCreator用于創建返回給客戶端的響應信息,spring mvc提供了靜態工廠方法MockRestResponseCreators進行操作;具體的API如下:

DefaultResponseCreator withSuccess() :返回給客戶端200(OK)狀態碼響應;

DefaultResponseCreator withSuccess(String body, MediaType mediaType)/DefaultResponseCreator withSuccess(byte[] body, MediaType contentType)/DefaultResponseCreator withSuccess(Resource body, MediaType contentType):返回給客戶端200(OK)狀態碼響應,且返回響應內容體和MediaType;

DefaultResponseCreator withCreatedEntity(URI location):返回201(Created)狀態碼響應,并返回響應頭“Location=location";

DefaultResponseCreator withNoContent() :返回204(NO_CONTENT)狀態碼響應;

DefaultResponseCreator withBadRequest() :返回400(BAD_REQUEST)狀態碼響應;

DefaultResponseCreator withUnauthorizedRequest()?:返回401(UNAUTHORIZED)狀態碼響應;

DefaultResponseCreator withServerError() :返回500(SERVER_ERROR)狀態碼響應;

DefaultResponseCreator withStatus(HttpStatus status):設置自定義狀態碼;

?

對于DefaultResponseCreator還提供了如下API:

DefaultResponseCreator body(String content) /DefaultResponseCreator body(byte[] content)/DefaultResponseCreator body(Resource resource):內容體響應,對于String content 默認是UTF-8編碼的;

DefaultResponseCreator contentType(MediaType mediaType) :響應的ContentType;

DefaultResponseCreator location(URI location)?:響應的Location頭;

DefaultResponseCreator headers(HttpHeaders headers):設置響應頭;

?

2.5 測試示例

?

測試查找

請參考之前的testFindById;

?

測試新增

提交JSON數據進行新增

Java代碼?? 收藏代碼
  1. @Test ??
  2. public ? void ?testSaveWithJson()? throws ?Exception?{??
  3. ????User?user?=? new ?User();??
  4. ????user.setId(1L);??
  5. ????user.setName( "zhang" );??
  6. ????String?userJson?=?objectMapper.writeValueAsString(user);??
  7. ??
  8. ????String?uri?=?baseUri;??
  9. ????String?createdLocation?=?baseUri?+? "/" ?+? 1 ;??
  10. ??
  11. ????mockServer??
  12. ????????????.expect(requestTo(uri))?? //驗證請求URI ??
  13. ????????????.andExpect(jsonPath( "$.name" ).value(user.getName()))? //驗證請求的JSON數據 ??
  14. ????????????.andRespond(withCreatedEntity(URI.create(createdLocation)).body(userJson).contentType(MediaType.APPLICATION_JSON));? //添加響應信息 ??
  15. ??
  16. ??
  17. ????restTemplate.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList( new ?MappingJackson2HttpMessageConverter()));??
  18. ????ResponseEntity<User>?responseEntity?=?restTemplate.postForEntity(uri,?user,?User. class );??
  19. ??
  20. ????assertEquals(createdLocation,?responseEntity.getHeaders().get( "Location" ).get( 0 ));??
  21. ????assertEquals(HttpStatus.CREATED,?responseEntity.getStatusCode());??
  22. ????assertEquals(user,?responseEntity.getBody());??
  23. ??
  24. ????mockServer.verify();??
  25. }??

提交XML數據進行新增

Java代碼?? 收藏代碼
  1. @Test ??
  2. public ? void ?testSaveWithXML()? throws ?Exception?{??
  3. ????User?user?=? new ?User();??
  4. ????user.setId(1L);??
  5. ????user.setName( "zhang" );??
  6. ????ByteArrayOutputStream?bos?=? new ?ByteArrayOutputStream();??
  7. ????marshaller.marshal(user,? new ?StreamResult(bos));??
  8. ????String?userXml?=?bos.toString();??
  9. ??
  10. ????String?uri?=?baseUri;??
  11. ????String?createdLocation?=?baseUri?+? "/" ?+? 1 ;??
  12. ??
  13. ????mockServer??
  14. ????????????.expect(requestTo(uri))?? //驗證請求URI ??
  15. ????????????.andExpect(xpath( "/user/name/text()" ).string(user.getName()))? //驗證請求的JSON數據 ??
  16. ????????????.andRespond(withCreatedEntity(URI.create(createdLocation)).body(userXml).contentType(MediaType.APPLICATION_XML));? //添加響應信息 ??
  17. ??
  18. ????restTemplate.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList( new ?Jaxb2RootElementHttpMessageConverter()));??
  19. ????ResponseEntity<User>?responseEntity?=?restTemplate.postForEntity(uri,?user,?User. class );??
  20. ??
  21. ????assertEquals(createdLocation,?responseEntity.getHeaders().get( "Location" ).get( 0 ));??
  22. ????assertEquals(HttpStatus.CREATED,?responseEntity.getStatusCode());??
  23. ??
  24. ????assertEquals(user,?responseEntity.getBody());??
  25. ??
  26. ????mockServer.verify();??
  27. }??

??

測試修改?

Java代碼?? 收藏代碼
  1. @Test ??
  2. public ? void ?testUpdate()? throws ?Exception?{??
  3. ????User?user?=? new ?User();??
  4. ????user.setId(1L);??
  5. ????user.setName( "zhang" );??
  6. ??
  7. ????String?uri?=?baseUri?+? "/{id}" ;??
  8. ??
  9. ????mockServer??
  10. ????????????.expect(requestTo(uri))?? //驗證請求URI ??
  11. ????????????.andExpect(jsonPath( "$.name" ).value(user.getName()))? //驗證請求的JSON數據 ??
  12. ????????????.andRespond(withNoContent());? //添加響應信息 ??
  13. ??
  14. ????restTemplate.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList( new ?MappingJackson2HttpMessageConverter()));??
  15. ????ResponseEntity?responseEntity?=?restTemplate.exchange(uri,?HttpMethod.PUT,? new ?HttpEntity<>(user),?(Class)? null ,?user.getId());??
  16. ??
  17. ????assertEquals(HttpStatus.NO_CONTENT,?responseEntity.getStatusCode());??
  18. ??
  19. ????mockServer.verify();??
  20. }??

?

測試刪除?

Java代碼?? 收藏代碼
  1. @Test ??
  2. public ? void ?testDelete()? throws ?Exception?{??
  3. ????String?uri?=?baseUri?+? "/{id}" ;??
  4. ????Long?id?=?1L;??
  5. ??
  6. ????mockServer??
  7. ????????????.expect(requestTo(baseUri?+? "/" ?+?id))?? //驗證請求URI ??
  8. ????????????.andRespond(withSuccess());? //添加響應信息 ??
  9. ??
  10. ????ResponseEntity?responseEntity?=?restTemplate.exchange(uri,?HttpMethod.DELETE,?HttpEntity.EMPTY,?(Class)? null ,?id);??
  11. ????assertEquals(HttpStatus.OK,?responseEntity.getStatusCode());??
  12. ??
  13. ????mockServer.verify();??
  14. }??

?

通過Mock Server的最大好處是不需要啟動服務器,且不需要服務預先存在就可以測試;如果服務已經存在,通過Spring Boot進行測試也是個不錯的選擇。

?

?

再來回顧下測試步驟

1、準備測試環境

首先創建RestTemplate,然后通過MockRestServiceServer.createServer(restTemplate)創建一個Mock Server,其會自動設置restTemplate的requestFactory為RequestMatcherClientHttpRequestFactory(restTemplate發送請求時都通過ClientHttpRequestFactory創建ClientHttpRequest)。

2、調用API

即restTemplate.getForEntity(uri, User.class, id)訪問rest web service;

3、斷言驗證

3.1、客戶端請求斷言驗證

如mockServer.expect(requestTo(requestUri)).andExpect(method(HttpMethod.GET)):即會驗證之后通過restTemplate發送請求的uri是requestUri,且請求方法是GET;

3.2、服務端響應斷言驗證

首先通過mockServer.andRespond(withSuccess(new ObjectMapper().writeValueAsString(user), MediaType.APPLICATION_JSON));返回給客戶端響應信息;

然后restTemplate就可以得到ResponseEntity,之后就可以通過斷言進行驗證了;

4、 卸載測試環境

Spring MVC測試框架詳解——客戶端測試


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美 日本 | 亚洲国产成人久久77 | 欧美又黄又嫩大片a级 | 国产伦精品一区二区三区免 | 欧美30p| 亚洲精品久久久久久久777 | 精品精品国产理论在线观看 | 五月天久久婷婷 | 尤物视频在线观看视频 | 免费一级毛片无毒不卡 | 久草视频精品在线 | 国产专区精品 | 亚洲精品一区二区三区四区 | 九九爱精品视频 | 毛片免费视频播放 | 女人洗澡一级毛片一级毛片 | 性大特级毛片视频 | 国产精品免费视频播放 | 欧美激情综合亚洲一二区 | 国产精品真实对白精彩久久 | 精品91自产拍在线观看99re | 日韩欧美高清 | 国产精品99久久久久久宅男 | 成人一区专区在线观看 | 亚洲精品国产第一区二区多人 | 久久精品福利视频 | 精品看片 | 欧美激情久久欧美激情 | 91福利刘玥国产在线观看 | 午夜视频福利在线 | 亚洲成人在线免费观看 | 国产日韩欧美中文 | 国产精品国产自线在线观看 | 精品国产乱码一区二区三区 | 91精品国产露脸在线 | 亚洲日本va | 久久亚洲精品一区二区三区浴池 | 久久99久久精品国产99热 | 国产亚洲男人的天堂在线观看 | 玖玖精品视频 | 欧美黄色三级视频 |