春天的集成测试
最后修改:2021年2月24日
1.概述
集成测试通过验证系统的端到端行为在应用程序开发周期中扮演重要作用。
在本文中,我们将看到我们如何利用Spring MVC测试框架,以便编写和运行测试控制器而不明确启动Servlet容器的集成测试。
2.准备
要运行本文中使用的集成测试,需要几个Maven依赖项。首先,我们需要最新的junit-jupiter-engine那junit-jupiter-api,春季测试依赖性:
<依赖项> org.junit.jupiter groupID> JUNIT-JUPITER-ENGINE ARTIFACTID> 5.7.0 version> test scope> 依赖项> <依赖项> org.junit.jupiter groupID> JUnit-Jupiter-API Artifactid> 5.7.0 version> test scope> 依赖项> <依赖项> org.springframework groupID> Spring-test Artifactid> 5.3.3 version> test scope> 依赖项>
<依赖> < groupId > org。hamcrest artifactId> 2.2 test com.jayway。jsonpath artifactId> 2.5.0 test 依赖>
3. Spring MVC测试配置
现在,让我们介绍如何配置和运行启用Spring的测试。
3.1。使用JUnit 5启用Spring测试
JUNIT 5定义了一个扩展界面,课程可以与JUnit测试集成。
我们可以启用此扩展通过添加@extendwith.注释到我们的测试类并指定要加载的扩展名。要运行Spring测试,我们使用springextension.class。
我们还需要@contextConfiguration.注释来加载上下文配置和引导我们测试将使用的上下文。
我们来看一下:
@ContextConfiguration(classes = {ApplicationConfig.class}) @WebAppConfiguration公共类GreetControllerIntegrationTest {....}
注意如何,在@ContextConfiguration,我们提供applicationconfig.class.配置类,该类加载了此特定测试所需的配置。
我们在此处使用Java配置类来指定上下文配置。同样,我们可以使用基于XML的配置:
@ContextConfiguration(位置= {"})
最后,我们还用@WebAppConfiguration.,它将加载web应用程序上下文。
默认情况下,它在path上查找根web应用程序src / main / webapp。我们可以通过简单地传递这个位置来覆盖这个位置价值属性:
@WebAppConfiguration (value = " ")
3.2。这WebApplicationContext.目的
WebApplicationContext.提供web应用程序配置。它将所有应用程序bean和控制器加载到上下文中。
我们现在可以将Web应用程序上下文连接到测试:
@Autowired私人WebApplicationContext WebApplicationContext;
3.3。嘲笑Web上下文豆
MockMvc提供对Spring MVC测试的支持。它封装了所有Web应用程序bean,并使它们可用于测试。
让我们看看如何使用它:
私人模仿Mockmvc;@beforeeach公共void setup()抛出异常{this.mockmvc = mockmvcbuilders.webappcontextsetup(this.webapplicationscontext).build();}
我们初始化mockmvc.对象@beforeeach.注释方法使我们不必在每个测试中初始化它。
3.4。验证测试配置
我们来验证一下WebApplicationContext.目的 (WebApplicationContext.) 适当地。我们也会检查正确的servletContext正在附上:
@test public void给gentwac_whenservletContext_thenitProvideGreetController(){servletContext servletContext = webapplicationscontext.getservletContext();assert.assertnotnull(servletContext);assert.asserttrue(servletcontext instanceof mockservletContext);assert.assertnotnull(WebApplicationContext.getBean(“HavoryController”));}
请注意,我们也在检查一个GreetController.javaBean存在于web环境中。这将确保正确加载Spring bean。至此,集成测试的设置已经完成。现在,让我们看看如何使用MockMvc对象。
4.写入集成测试
在本节中,我们将通过测试框架进行可用的基本操作。
我们将展示如何使用路径变量和参数发送请求。此外,我们将遵循一些示例,该示例显示如何断言正确的视图名称已解决,或者响应正文如预期的那样。
如下所示的片段使用m的静态导入ockMvcRequestBuilders或mockmvcresultmatchers.类。
4.1。验证查看名称
我们可以援引/主页从我们的测试中的终点:
http://localhost:8080/spring-mvc-test/
或
http:// localhost:8080 / spring-mvc-test /主页
首先,让我们看看测试代码:
@test public voidedhomepageuri_whenmockmvc_thenreturnsindexjspviewname(){this.mockmvc.perform(get(“/ homepage”))。和do(print()).Andexpect(查看()。名称(“索引”));}
让我们打破:
- 履行()方法将调用Get Request方法,返回结果。使用此结果,我们可以对响应具有断言预期,例如其内容,HTTP状态或标题金宝搏官网188be
- andDo (print ())将打印请求和响应。如果出现错误,这有助于了解详细视图
- 一下动身()将期待提供的论点。在我们的情况下,我们期待通过“索引”返回mockmvcresultmatchers.view()
4.2。验证响应主体
我们会援引这件事/迎接我们测试的端点为:
http:// localhost:8080 / spring-mvc-test / break
预期的产出将是:
{“ID”:1,“消息”:“Hello World !!!”}
让我们看看测试代码:
@test public void gendgreegeturi_whenmockmvc_thenverifyResponse(){mvcresult mvcresult = this.mockmvc.perform(get(“/ break”)).anddo(print())。Andexpect(status()。isok()).Andexpect(jsonpath(jsonpath(jsonpath).Andexpect(jsonpath(jsonpath(jsonpath).message“)。价值(”Hello World !!!“)).Andreturn();assert.assertequals(“application / json; charset = utf-8”,mvcresult.getResponse()。GetContentType());}
让我们来看看到底发生了什么:
- 一下动身(MockMvcResultMatchers.status () .isOk ())将验证响应HTTP状态是好吧(200)。这确保了该请求已成功执行
- Andexpect(MockMvcresultMatchers.jsonPath(“$。消息”)。值(“Hello World !!!”))将验证与参数匹配的响应内容匹配“你好,世界!!!”。在这里,我们使用jsonPath,其中提取响应内容并提供所请求的值
- andReturn ()将返回MvcResult当我们必须验证库无法直接可实现的内容时使用的对象。在这种情况下,我们添加了assertequal匹配从中提取的响应的内容类型MvcResult目的
4.3.通过路径变量发送GET请求
我们会援引这件事/ prethwithvariable / {name}我们测试的端点为:
http:// localhost:8080 / spring-mvc-test / greetWithPathVariable / John
预期的产出将是:
{“ID”:1,“消息”:“Hello World John !!!”}
让我们看看测试代码:
@test public voidedgroiturewithpathvariabies_whenmockmvc_thenresponse ok(this.mockmvc .perform(get(“/ greetwithpathvariable / {name}”,“John”)).anddo(print())。Andexpect(status()。isok()).Andexpect(content()。contentType(“application / json; charset = utf-8”)).Andexpect(jsonpath(jsonpath(“$。消息”)。价值(“Hello World John !!!”));}
MockMvcRequestBuilders。get (" / greetWithPathVariable /{名称}”,“约翰”)将发送请求“/ greetWithPathVariable /约翰”。
这对于可读性和知道URL中动态设置了哪些参数变得更容易了。注意,我们可以根据需要传递任意多的路径参数。
4.4。使用查询参数发送GET请求
我们会援引这件事/ greetWithQueryVariable?name = {name}我们测试的端点为:
http:// localhost:8080 / spring-mvc-test / greetwithqueryvariable?name = John%20doe
在这种情况下,预期输出将是:
{“ID”:1,“消息”:“Hello World John Doe !!!”}
现在,让我们看看测试代码:
@test public void给gentgreeturiwithqueryparameter_whenmockmvc_thenresponse ok(the.mockmvc.perform(get(“/ greetwithqueryvariable”).param(“名称”,“John Doe”))。Anddo(print())。Andexpect(status()。isok()).Andexpect(content()。contentType(“application / json; charset = utf-8”)).Andexpect(jsonpath(jsonpath(“$。消息”)。价值(“Hello World John Doe !!!”));}
Param(“名字”,“John Doe”)会在GET请求中附加查询参数吗。这类似于/ greetWithQueryVariable?Name = John%20doe”。
查询参数也可以使用URI模板样式实现:
this.mockmvc.perform(get(“/ greetwithqueryvariable?name = {name}”,“John Doe”));
4.5。发送POST请求
我们会援引这件事/ greetWithPost我们测试的端点为:
http://localhost:8080/spring-mvc-test/greetWithPost
我们应该获得产出:
{“ID”:1,“消息”:“Hello World !!!”}
我们的测试代码是:
@Test public void givengreturiwithpost_whenmockmvc_thenverifyresponse () {this.mockMvc.perform(post("/ gretwithpost ")). anddo (print()) . andexpect (status(). isok ()). andexpect (content() . contenttype ("application/json;charset=UTF-8")) . andexpect (jsonPath("$.message"))。值(“Hello World !”));}
mockmvcrequestbuilders.post(“/ greetwithpost”)将发送邮寄请求。我们可以像前面一样以类似的方式设置路径变量和查询参数,而表单数据只能通过Param()方法,类似于以下查询参数:
http://localhost:8080/spring-mvc-test/greetWithPostAndFormData
则数据为:
ID = 1;名称= JOHN%20doe
因此,我们应该得到:
{“ID”:1,“消息”:“Hello World John Doe !!!”}
让我们看看我们的测试:
@test public void gendgreegeture_whenmockmvc_thenverifyResponse()抛出异常{mvcresult mvcresult = this.mockmvc.perform(mockmvcrequestbuilders.get(“/问候”)).anddo(print()).Andexpect(mockmvcresultmatchers.status()。isok())。Andexpect(MockMvcresultMatchers.jsonPath(“$。消息”)。价值(“Hello World !!!”)).Andreturn();assertequals(“application / json; charset = utf-8”,mvcresult.getResponse()。GetContentType());}
在上面的代码段中,我们已添加两个参数:ID为“1”名称作为“John Doe”。
5。MockMvc限制
MockMvc提供优雅且易于使用的API,可调用Web端点并同时检查和断言其响应。尽管有其所有好处,但它有一些局限性。
首先,它确实使用了一个子类Dispatcherservlet.处理测试请求。更具体地说,是TestDispatcherServlet负责调用控制器并执行所有熟悉的春季魔法。
这MockMvc班级包装这TestDispatcherServlet在内部。因此,每次我们发送请求时使用履行()方法,MockMvc将使用底层的TestDispatcherServlet直接。因此,没有建立真正的网络连接,因此,在使用时我们不会测试整个网络堆栈MockMvc。
还,由于Spring准备虚假的Web应用程序上下文来模拟HTTP请求和响应,因此可能不支持全吹的Spring应用程序的所有功能。
例如,此模拟设置不支持HTTP重定向。这似乎最初可能似乎没有重要。但是,Spring Boot通过将当前请求重定向到时,通过将当前请求重定向来处理一些错误/错误端点。所以,如果我们正在使用MockMvc,我们可能无法测试一些API失败。
作为替代品MockMvc,我们可以设置更真实的应用程序然后使用resttemplate.甚至放心来测试我们的应用程序。
例如,使用Spring启动很简单:
@SpringBootTest(webEnvironment = DEFINED_PORT) public class GreetControllerRealIntegrationTest {@Before public void setUp() {RestAssured。端口= DEFAULT_PORT;} @Test public void givengreturi_whenenendingreq_thenverifyresponse () {given().get("/greet") .then() .statusCode(200);}}
在这里,我们甚至不需要添加@extendwith(springextension.class)。
这样,每个测试都将对在随机TCP端口上侦听的应用程序进行真实HTTP请求。
6.结论
在本教程中,我们实现了几个简单的支持spring的集成测试。
我们也看了WebApplicationContext.和MockMvc对象创建,在调用应用程序的终点方面发挥了重要作用。
我们介绍了如何通过参数传递的变化以及如何验证HTTP响应状态,标题和内容的变化发送Get和Post请求。
作为结束语,我们也评估了一些局限性MockMvc。了解这些限制可以指导我们了解我们如何实施测试的明智决定。金宝搏官网188be
最后,可以使用所有这些示例和代码片段的实现在github上。