SpringBoot之data使用RestDocs

1.声明

当前内容主要用于测试和使用SpringBoot-data的RestDocs方式生成测试api

  1. spring-data-jpa方式操作内存h2数据库
  2. 使用restdocs生成测试文档

2.当前pom依赖

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.18.RELEASE</version>
	</parent>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.restdocs</groupId>
			<artifactId>spring-restdocs-mockmvc</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path -->
		<dependency>
			<groupId>com.jayway.jsonpath</groupId>
			<artifactId>json-path</artifactId>
			<version>2.4.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.restdocs</groupId>
			<artifactId>spring-restdocs-mockmvc</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<!-- <plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<configuration>
					<includes>
						<include>**/*Test.java</include>
					</includes>
				</configuration>
			</plugin> -->
			<plugin>
				<groupId>org.asciidoctor</groupId>
				<artifactId>asciidoctor-maven-plugin</artifactId>
				<version>1.5.8</version>
				<executions>
					<execution>
						<id>generate-docs</id>
						<phase>prepare-package</phase>
						<goals>
							<goal>process-asciidoc</goal>
						</goals>
						<configuration>
							<backend>html</backend>
							<doctype>book</doctype>
							<attributes>
								<snippets>${project.build.directory}/generated-snippets</snippets>
							</attributes>
						</configuration>
					</execution>
				</executions>
				<dependencies>
					<dependency>
						<groupId>org.springframework.restdocs</groupId>
						<artifactId>spring-restdocs-asciidoctor</artifactId>
						<version>2.0.3.RELEASE</version>
					</dependency>
				</dependencies>
			</plugin>
		</plugins>
	</build>

其中:<snippets>${project.build.directory}/generated-snippets</snippets>,表示生成adoc文件的路径(就是测试后的分散文件)

3.基本的SpringBootDemo

1.配置类:Config .java

@Configuration
@EntityScan(basePackages = "com.hy.springboot.restdoc.entity")
@EnableJpaRepositories(basePackages = "com.hy.springboot.restdoc.dao")
public class Config {

}

2.实体类:User .java

@Entity
public class User {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Integer id;
	private String name;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + "]";
	}

}

3.dao层:UserRepository .java

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.hy.springboot.restdoc.entity.User;

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {

}

4.controller层:UserController .java


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.hy.springboot.restdoc.dao.UserRepository;
import com.hy.springboot.restdoc.entity.User;

@RestController
public class UserController {
	@Autowired
	UserRepository userRepository;

	@RequestMapping(value = "/getUserById/{id}", produces = {MediaType.APPLICATION_JSON_VALUE })
	public User getUserById(@PathVariable Integer id) {
		return userRepository.findById(id).get();
	}

	@RequestMapping(value = "/findAll")
	public Object findAll(@PathVariable Integer id) {
		return userRepository.findAll();
	}

	@RequestMapping(value = "/addUser", produces = { MediaType.APPLICATION_JSON_VALUE })
	public String addUser(User user) {
		userRepository.save(user);
		return "{\"result\":\"success\",\"msg\":\"添加用户成功!\"}";
	}
}

注意这里的controller中的方法一定要返回json数据,否则在使用RestDocs的时候会出现JsonPath解析错误!

5.入口类:SpringBootDataRestDocApp .java


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;

/**
 * @author admin
 * @createTime 2021-03-01 11:53:24
 * @description 当前内容主要用于测试和使用SpringBoot-data-restdoc
 * 
 */
@SpringBootApplication
public class SpringBootDataRestDocApp 
{
    public static void main( String[] args )
    {
        SpringApplication.run(SpringBootDataRestDocApp.class, args);
        //String json="{\"id\":1,\"name\":\"admin\"}";
        //DocumentContext documentContext = JsonPath.parse(json);
        //Object read = JsonPath.read(json,"id");
        //System.out.println(read);
    }
}

4.测试类(即生成RestDocs的类)

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.results.ResultMatchers;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.request.PathParametersSnippet;
import org.springframework.restdocs.request.RequestDocumentation;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import com.hy.springboot.restdoc.config.Config;
import com.hy.springboot.restdoc.controller.UserController;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import javax.servlet.RequestDispatcher;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringBootDataRestDocApp.class)
@AutoConfigureRestDocs(outputDir = "target/generated-snippets")
@WebAppConfiguration
public class AppTest {

	MockMvc mockMvc;

	@Autowired
	WebApplicationContext webApplicationContext;

	@Rule
	public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

	// 测试之前
	@Before
	public void startUp() {
		// 通过MockMvcBuilders和当前web应用创建MockMvc
		/*
		 * mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
		 * .apply(documentationConfiguration(this.restDocumentation)).build();
		 */
		this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext)
				.apply(documentationConfiguration(this.restDocumentation))
				.alwaysDo(document("{ClassName}/{methodName}")).build();
	}

	@Test
	public void addUser() throws Exception {
		// MockMvcResultMatchers.
		// relaxedResponseFields
		this.mockMvc
				.perform(get("/addUser").param("name", "admin"))
				.andDo(print()) // 打印请求信息
				.andExpect(status().isOk()) // 期望是一个好请求
				.andExpect(jsonPath("result", is(notNullValue())))
				.andExpect(jsonPath("msg", is(notNullValue())))
				.andDo(document("{ClassName}/{methodName}", responseFields(
						fieldWithPath("result").description("当前操作的结果"), 
						fieldWithPath("msg").description("当前操作结果对应的消息")
				)));
	}

	@Test
	public void getUserById() throws Exception {
		this.mockMvc.perform(get("/getUserById/{id}", 1))
				.andDo(print())
				.andExpect(status().isOk())
				.andExpect(jsonPath("id", is(notNullValue())))
				.andExpect(jsonPath("name", is(notNullValue())))
				.andDo(document("{ClassName}/{methodName}", RequestDocumentation
						.pathParameters(
								RequestDocumentation.parameterWithName("id").description("需要查询的用户编号"))//
						, responseFields(
								fieldWithPath("id").description("添加后的自动生成用户编号"),
								fieldWithPath("name").description("添加的用户名称"))));
	}

}

注意事项:

  1. document("{ClassName}/{methodName}")
    表示生成文档样式:当前类名称/当前@Test方法名称,这个关系到后面的index.adoc中的表达式
    在这里插入图片描述
  2. jsonPath表示在返回的json数据中取出指定的key,如果返回不是json那么报错
  3. RequestDocumentation.parameterWithName("id")表示路径{id}参数的名称
  4. fieldWithPath(“name”),表示字段描述
  5. 最重要的一个,必须在当前项目的src下的main文件夹中创建asciidoc文件夹,最后在其中创建index.adoc(index.adoc中主要为显示html的样式)
    在这里插入图片描述
  6. @AutoConfigureRestDocs(outputDir = "target/generated-snippets"),表示生成adoc的文件位置

5.编写index.adoc的内容

= API
:toc: left
:toclevels: 4
:toc-title: 接口目录

[[user]]
== 1.用户管理

[[user-getById]]
=== 根据用户id获取用户信息
operation::AppTest/getUserById[]

[[user-addUser]]
=== 添加用户信息
operation::AppTest/addUser[]

其中operation::AppTest/getUserById[]表示迭代AppTest文件夹中的getUserById文件夹中的所有adoc文件并进行转换写入

6.maven启动打包

使用cmd切换到该项目的pom文件下,执行mvn package

在这里插入图片描述
直到出现全部绿即可!

此时生成一个html文件位于:当前项目\target\generated-docs这里

在这里插入图片描述

使用浏览器打开即可:
在这里插入图片描述

此时操作成功!

7.总结

1.SpringBoot-data中使用RestDocs感觉比较复杂,需要手动编写测试环境,并且,对应测试的方法中每个返回的结果都必须是json数据

2.小心index.adoc中的表达式,错了一个就会出现无法连接其他的adoc文件的情况

3.当前的测试方法中必须填写andExpect即返回json的属性,否则报错,并且响应的状态也需要写清楚,个人感觉比Swagger复杂多了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值