Unit testing with Spring rest docs

Source: Internet
Author: User
Tags documentation json

Spring REST Docs helps you manage RESTful service documents, use Asciidoctor to write documents, and automatically generate fragments using Spring MVC Test. first, what style is called rest style?

Everyone in the programming world should have heard that restful style can improve the performance of the project, and now it's all over the place that our project is restful, so what's the rest style? Just to give an example, you can understand:
For example, now there is a URL:
https://www.oschina.net/news/66853/spring-rest-docs-1-0-0
The 66853 here may be a dedicated ID or other related mappings, and we cannot know from here what it really refers to.
And if it's a non-restful URL, it would look like this:
https://www.oschina.net/news/uid?userUid=66853/spring-rest-docs-1-0-0
Xxx?xxx= XXX so that everyone can guess the URL, later encrypted sent to the backstage, and then there is a so-called rest more popular. How to generate API documentation using spring rest doc.

Example: Springboot engineering, exposing the HTTP interface through the API documentation, requires only JUnit unit tests and spring MOCKMVC to generate the document.
The Springrestdoc framework uses tests to generate a description of the rest interface: You can simply describe parameters and return values, generate URLs and return use cases, and combine unit tests with the current MOXKMVC framework to produce asciidoctor document fragments.
Cons: You can only generate fragments at this time, inheriting an entire API document and need to write manually. Of course, the more tests you have, the more detailed the content of the document is.
Solution : Here can only produce fragments of the article, not automatically integrated into a whole document of the shortcomings, you can use my previous introduction of the swagger to solve. Swagger has a strong ability and confidence to do this thing, you can rest assured that it is good. Basic Configuration

Software: Idea
jdk:1.8
maven:3.0+ Simple rough, we start directly from the operation ha: 1. Introducing a corresponding Maven dependency in the Pom.xml file

<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactid>spring-boot-starter-test </artifactId>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework.restdocs</groupId>
      <artifactId>spring-restdocs-mockmvc< /artifactid>
      <scope>test</scope>
    </dependency>
  </dependencies>
2. Add the settings in the re-test class:

Restdoc is to generate snippets files from unit tests and then snippets to generate HTML documents based on plug-ins
settings in the test class:
(1)

Public junitrestdocumentation restdocumentation =
new Junitrestdocumentation ("Target/generated-snippets");

(2) then configure MOCKMVC or rest assured in the @before method:

Setting up your JUnit tests

Private Mockmvc Mockmvc;
@Autowired
private Webapplicationcontext context;
@Before public
void SetUp () {
This.mockmvc = Mockmvcbuilders.webappcontextsetup (this.context)
. Apply ( Documentationconfiguration (this.restdocumentation))
. Build ();
}

The MOCKMVC instance is configured with a configuration mockmvcrestdocumentationconfigurer. An instance of this class can be obtained from the static Documentationconfiguration () method in Org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.

Setting up your tests without JUnit
Unlike above, @rule is not required and replaced with junitrestdocumentation.

Private Manualrestdocumentation restdocumentation =
new Manualrestdocumentation ("Target/generated-snippets");

Similarly, the setup () Mockmvc in the Setup () method will change to this:

Private Mockmvc Mockmvc;
@Autowired
private Webapplicationcontext context;
@BeforeMethod public
void SetUp (method) {
This.mockmvc = Mockmvcbuilders.webappcontextsetup ( This.context)
. Apply (Documentationconfiguration (this.restdocumentation))
. Build ();
This.restDocumentation.beforeTest (GetClass (), Method.getname ());
}

However, after each test, the Manualrestdocumentation.aftertest () method is called once:

@AfterMethod public
void TearDown () {
this.restDocumentation.afterTest ();
}
3.Invoking the RESTful service

Once the testing framework is configured, it can try to integrate restful services, with detailed instructions for the requests and responses.
Give a chestnut: (Kotlin

    @Resource private lateinit var context:webapplicationcontext
    private lateinit var mockmvc:mockmvc

    // Set the location of the test Fragment generation folder
    @Rule @JvmField var restdocumentation = junitrestdocumentation ("target/asciidoc/snippets")

    @ Before Fun
    setUp () {
        This.mockmvc = Mockmvcbuilders.webappcontextsetup (context)
                .apply< Defaultmockmvcbuilder> (Documentationconfiguration (this.restdocumentation))
                . Build ()
    }

@Test Fun
    Create () {
    val parentid = "Sssssssssss"
    val request = post ("/groups/$parent")
    This.mockMvc.perform (Request).
                andexception (status.iscreated).
                Anddo (print ())
                . Anddo (Document (" {MethodName} ", Preprocessrequest (Prettyprint ()))
    }

As an example in the official documentation for spring REST docs: (Java)
We can add some specific descriptions of the parameters in Anddo ():

This.mockMvc.perform (Get ("/locations/{latitude}/{longitude}", 51.5072,0.1275))
            . Andexpect (Status (). IsOk ())
            . Anddo (document ("Locations",
            pathparameters (Parameterwithname ("latitude"). Description ("The location ' s
latitude "), Parameterwithname (" longitude "). Description (" The location ' s Longitude ")))
;

Some usage of the parameters in the official documentation for these spring REST docs I will not go into detail, because it is clear that the code looks untidy, and there is something better to replace it, so we directly learn to better solve the "property and reply message detailed description" Solution to the problem is good ~

The above is a summary of the knowledge learned in Springrestdocs's official documentation.

" So what's the good solution?" "
Is the springfox-swagger that I mentioned in the last article, it is a power of the strong, why? Not much to say, to give a simple chestnut:
When using the Springfox-swagger framework, we are adding detailed annotations to the API in each class of the controller layer:
(Kotlin) Of course, to use the following code pattern, you need to configure the integration Springfox-swagger in your project. (Springboot+springdatajpa+springframework+springfox-swagger)

 @RestController @Api (value = "User", Description = "The chapter of User") @RequestMapping ("/ Users ", produces = arrayof (Mediatype.application_json_utf8_value)) class Itemcontroller {@ApiOperation (VALUE =" Crea Teuser ", notes =" Create a user ") @ApiImplicitParams (apiimplicitparam (name =" Name ", value =" username ", Paramtype =" path ", R Equired = true, DataType = "String"), Apiimplicitparam (name = "Age", value = "Ages of the user", Paramtype = "path", required = t Rue, DataType = "Int")) @ApiResponses (apiresponse (code = $, message = "created successfully", Response = User::cla SS), Apiresponse (code = 404, Message = "Not Found", response = Void::class)) @PostMapping ("{Name}/age/{age } ", consumes = arrayof (Mediatype.application_json_utf8_value)) Fun Create (@PathVariable (" name ") username:string, @Pat 
Hvariable ("Age") Userage:int): responseentity<any> {//The code implemented here is omitted//... return user} }

Some simple annotations about the API are described in the previous article.

Summary :
(1) Springrestdocs is mainly used to generate test code fragments during testing, and to add some simple instructions in the test fragments;
(2) Swagger is mainly used to provide the test interface, and integrate the Generation API interface documentation;
(3) MOCKMVC is a test framework for spring MVC, based on a restful style of SPRINGMVC test that can test the completed process. Information about MOCKMVC can be viewed at: http://www.cnblogs.com/lyy-2016/p/6122144.html he writes very well and can read the blog I wrote before. code Example:

The following is a complete example, combined with Springboot+springdatajpa+springmvc+mockmvc+springrestdocs+springfox-swagger, to complete the production of a detailed API interface documentation. Step One: Configure the dependency of the Swagger2+springrestdocs jar package in maven

Mavne will automatically download the jar package you need

<!--https://mvnrepository.com/artifact/io.springfox/springfox-swagger2---<dependency> &
            Lt;groupid>io.springfox</groupid> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupid>io .springfox</groupid> <artifactId>springfox-swagger-ui</artifactId> &LT;VERSION&G t;2.6.1</version> </dependency> <dependency> <groupid>org.springframew Ork.restdocs</groupid> <artifactId>spring-restdocs-mockmvc</artifactId> <vers ion>1.1.2.release</version> <scope>test</scope> </dependency> <d Ependency> <groupId>io.springfox</groupId> &LT;ARTIFACTID&GT;SPRINGFOX-STATICDOCS&L
      T;/artifactid>      <version>2.6.1</version> </dependency> 
Step Two: Configure Swagger2
    Import Org.springframework.context.annotation.Bean Import Org.springframework.context.annotation.Configuration Import org.springframework.http.ResponseEntity import Springfox.documentation.builders.ApiInfoBuilder import spri  Ngfox.documentation.builders.PathSelectors Import springfox.documentation.builders.RequestHandlerSelectors Import Springfox.documentation.service.ApiInfo Import springfox.documentation.service.Contact Import Springfox.documenta Tion.spi.DocumentationType Import springfox.documentation.spring.web.plugins.Docket Import springfox.documentation
    . swagger.web.UiConfiguration Import Springfox.documentation.swagger2.annotations.EnableSwagger2 @Configuration @EnableSwagger2 class Swagger2config {@Bean fun Restfulapi (): Docket {return Docket (Documentationt Ype. swagger_2). Genericmodelsubstitutes (Responseentity::class.java). Usedefaultresponsemessage
             S (True)   . Forcodegeneration (True). Select (). APIs (requesthandlerselectors. b Asepackage ("{You scanned the package for API annotations}"). Paths (Pathselectors.any ()). Build (). Pathmapp
                ing ("/"). Apiinfo (Apiinfo ())} Private Fun Apiinfo (): apiinfo {return Apiinfobuilder () . title ("API Documentation"). Description (this.description). Termsofserviceurl ("http://t Erms. XXX.com "). Contact (Contacts). Version (" 1.0.0 "). Build ()}

The @configuration annotation here, let spring load the configuration, @EnableSwagger2 enable Swagger2
and then create the docket bean through the CREATERESTAPI function, Apiinfo () Basic information that is used to create the API (these basic information is now available on the document page). The Select () function returns a Apiselectorbuilder instance that controls which interfaces are exposed to swagger, and this example is defined by the package path of the specified scan, and swagger scans all the controller-defined APIs under the package. and produces the contents of the document (except for requests specified by @apiignore). Step Three: Set some specifications for the swagger consolidated fragment generation API

    Import io.github.robwin.markup.builder.MarkupLanguage import io.github.robwin.swagger2markup.GroupBy Import io . Github.robwin.swagger2markup.Swagger2MarkupConverter Import org.junit.Before import org.junit.Test import org . Junit.runner.RunWith Import org.springframework.boot.test.context.SpringBootTest Import org.springframework.http. MediaType Import Org.springframework.test.context.junit4.SpringJUnit4ClassRunner Import ORG.SPRINGFRAMEWORK.TEST.W EB.SERVLET.MOCKMVC Import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get Import Org.sprin Gframework.test.web.servlet.result.MockMvcResultMatchers.status Import Org.springframework.test.web.servlet.setup.MockMvcBuilders Import Org.springframework.web.context.WebApplicationContext Import Springfox.documentation.staticdocs.Swagger2MarkupResultHandler.outputDirectory Import Springfox.documentation.staticdocs.SwaggerResultHandler Import Javax.annotation.ResourCe @Test @Throws (exception::class) Fun Converttoasciidoc () {//Get Swagger.json, write to OutputDir directory This.mockMvc.perform (Get ("/v2/api-docs"). Accept (Mediatype.application_json)). Anddo (Swaggerresulthandler . OutputDirectory (OutputDir). Build ()). Andexpect (Status (). isOk). Andreturn ()//Read The Swagger.json generated in the previous step is converted into AsciiDoc, written to OutputDir//This outputdir must be consistent with the plug-in <generated></generated> tag configuration S
                Wagger2markupconverter.from (OutputDir + "/swagger.json"). Withpathsgroupedby (GROUPBY.XXX)//Sort by XXX . Withmarkuplanguage (Markuplanguage.asciidoc)//format. Withexamples (Snippetdir). Buil D (). Intofolder (OutputDir)//output}

In unit testing, Springrestdocs generates snippets of code, which is the process of integrating a fragment into a JSON file and then converting it into a format. Fourth Step: Add some code for Springrestdocs and MOCKMVC in the test class for unit testing

    @Resource private lateinit var context:webapplicationcontext
    private lateinit var mockmvc:mockmvc

    @Rule @ Jvmfield var restdocumentation = 
                junitrestdocumentation ("{Springrestdocs the absolute path of the file that generated the test fragment}")

    @Before fun
    SetUp () {
        This.mockmvc = Mockmvcbuilders.webappcontextsetup (context)
                .apply<defaultmockmvcbuilder> ( Documentationconfiguration (this.restdocumentation))
                . Build ()
    }

Where. Apply (Documentationconfiguration (this.restdocumentation)) is the combination of MOCKMVC and Springrestdocs.
@Rule indicates that the test is currently in the JUnit test environment

    @Test fun
    Create () {
        val json = ' ""
                {
                    "userName": "UserName", "Age
                    ": "
        " "}" "" Val Request = post ("/users").
                ContentType ("{Production type}").
                content (JSON)
                . Accept ("{Consumption type}")

        This.mockMvc.perform (Request)
                Andexpect (status () iscreated)
                . Anddo (print ())
                . Anddo (Document (" CreateUser ", Preprocessresponse (Prettyprint ()))
    }

Here's a anddo () kind of usage, as I've said in previous articles. These are all used to simulate a MOCKMVC request.
Here the. Anddo (document ("CreateUser", Preprocessresponse (Prettyprint ())) is a few simple comments that belong to Springrestdocs in the generated test snippet Fifth step: Under the SWAGGER2 Scan package you set up, fill in the API annotations and refine the content of the properties and reply messages in the generated API documentation. The scan path here is usually the controller layer in the SPRINGMVC.

@ApiOperation (value = "CreateUser", notes = "Create a user")
 @ApiImplicitParams (
    apiimplicitparam (name = "Name", Value = "username", Paramtype = "path", required = true, DataType = "String"),
    apiimplicitparam (name = "Age", value = "Year of the user") Paramtype = "path", required = true, DataType = "Int")
    )
    @ApiResponses (
            apiresponse (code = $, message = "Create successful", response = User::class),
            apiresponse (code = 404, Message = "Not Found", response = Void::class)
    )
    @PostMap Ping ("{name}/age/{age}", consumes = arrayof (Mediatype.application_json_utf8_value)) Fun
    Create (@PathVariable (" Name ") username:string, @PathVariable (" age ") Userage:int): responseentity<any> {
       //As usual, some code in the middle implementation is omitted
        Return User
    }

All of the API annotations here, after the unit test is complete, run Swagger2 test, can be integrated into the API interface document. The rest will not be discussed.

Over ~
To be perfected revision

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.