使用Spring Boot和HTMLUnit进行端到端测试入门
首先
我是石田,负责圣诞节前夜的圣诞节降临日历,我在Mikatus株式会社担任应用开发工程师,使用Spring Boot 2写代码。
我正在负责的微服务中,没有端到端测试的机制,因此我决定引入它!目前正在进行调查。我希望能够分享在此过程中学到的知识,所以如果你打算在Spring中引入端到端的机制,可以参考一下这个作为第一步。
由于我仍然是个初学者,对于Spring来说还有很多不足之处和需要修正的地方,如果你能告诉我,我会非常高兴。
E2E 测试是指端到端测试 .
请查看这篇文章。
HTMLUnit是什么?
HTMLUnit是一款无GUI的浏览器,通过使用HTMLUnit,可以在虚拟浏览器上对HTML文档进行结构化处理。
另外,HTMLUnit还提供了用于操作结构化DOM的各种操作API(如向表单输入数据、点击链接、提交等),它是一个与JavaScript兼容性也很高的由Java编写的库。
根据我所了解,HTMLUnit本身并不提供测试功能,通常会与JUnit等测试框架结合在一起,用于E2E测试阶段。可以通过模拟浏览器进行测试,目前支持的浏览器包括Chrome、Firefox和Internet Explorer。
通过与Spring结合,可以自动验证以下测试用例:
1. 在表单的文本区域内输入姓名。
2. 提交表单。
3. 确认提交后,输入的姓名会在输出区域中显示。
这个库已经在Spring Framework 4中集成了。
HTMLUnit 是一个基于 Java 的开源浏览器自动化框架。您可以使用它来模拟网页加载和交互操作,非常适用于Web应用程序的功能测试和爬虫开发。HTMLUnit 提供了丰富的API,可以方便地操作网页元素、执行JavaScript代码以及获取和修改页面内容。使用HTMLUnit,您可以在不打开实际浏览器的情况下进行各种网页操作,从而提高效率和可靠性。无论是新手还是经验丰富的开发者,HTMLUnit 都是一个强大且灵活的工具,可以帮助您更轻松地处理Web应用程序的自动化任务。
MockMvc 是什么?
在使用Spring MVC项目构建的应用程序中,进行E2E测试时,另一个重要的关键词是MockMvc。这是Spring Test项目中包含的功能,它是与Spring MVC框架集成的状态下进行测试所必不可少的机制。通过使用MockMvc,我们可以模拟Spring MVC的行为,而不需要在应用程序服务器上进行部署,从而省去了准备服务器的麻烦,并且能够快速进行测试。
(1)测试用例方法是为DispatcherServlet设置请求数据(例如请求路径和请求参数)。
(2)MOckMvc对DispatcherServlet进行模拟请求。实际使用的DispatcherServlet被扩展为org.springframework.test.web.servlet.TestDispatcherServlet,用于测试。
(3)DispatcherServlet(Spring MVC的框架处理)调用与请求内容匹配的处理器(控制器)方法。
(4)测试用例方法接收MockMvc返回的执行结果,并验证执行结果的有效性。
春天全面初级入门-利用Spring Framework开发Java应用程序 引用
在生产环境中,通常情况下,Tomcat的Coyote和Catarina组件的类会接受客户端的请求,并将处理任务转交给Dispatcher Servlet。但是,现在Tomcat的功能已经消失了。
而且,以下网站上还进行了详细解释。
10.2.4. 如何使用在单元测试中使用的开源库。
运动环境
-
- Spring Boot 2.2.0
- JDK 1.8.0_211
情景
我們將進行實作,預計在以下情境中實現:確認在訊息輸入畫面輸入的文本能正確顯示在訊息確認畫面上。
实施
构建.gradle文件的配置
以下是构成如下。
plugins {
id 'org.springframework.boot' version '2.2.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('org.springframework.boot:spring-boot-devtools')
compile('org.springframework.boot:spring-boot-starter-cache')
compile group: 'net.sourceforge.htmlunit', name: 'htmlunit', version: '2.36.0'
compile group: 'org.w3c.css', name: 'sac', version: '1.3'
}
test {
useJUnitPlatform()
}
控制器的实现
package com.example.demo.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/message")
public class MessageController {
// メッセージ入力 Form の表示
@RequestMapping(value = "/showForm", method = RequestMethod.GET)
public String showForm() {
// message-form.html(メッセージ入力画面)を表示
return "message-form";
}
// メッセージ確認画面の表示
@RequestMapping(value = "/postMessage", method = RequestMethod.POST)
public String postMessage(@RequestParam("message") final String message, final Model model) {
// "message" という attributeName に対して post されてきた message の内容を model#addAttribute でマッピング
model.addAttribute("message", message);
// message-confirm.html(メッセージ確認画面)を表示
return "message-confirm";
}
}
创建模板文件。
信息输入表单模板
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>メッセージ入力画面</h1>
<form action="#" th:action="@{/message/processForm}" method="post">
Message: <input type="text" value="message" id="message" name="message" />
<input type="submit" />
</form>
</body>
</html>
消息确认模板
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>メッセージ確認画面</h1>
<span th:text="${message}" id="received"></span>
</body>
</html>
创建测试类
请查看代码中的解释以获取相关信息。
package com.example.demo;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.htmlunit.MockMvcWebClientBuilder;
import org.springframework.web.context.WebApplicationContext;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ExtendWith(SpringExtension.class) // (1)
@SpringBootTest // (2)
public class MessageControllerTest {
@Autowired
private WebApplicationContext webApplicationContext; // (3)
private WebClient webClient;
@BeforeEach
public void setup() {
webClient = MockMvcWebClientBuilder.webAppContextSetup(webApplicationContext).build(); // (4)
}
@Test
public void givenAMessage_whenSent_thenItShows() throws Exception {
String text = "Hello world!";
String url = "http://localhost/message/showForm";
// メッセージ入力画面( message-form.html )を取得
HtmlPage page = webClient.getPage(url);
// メッセージ入力画面の id = "message" の DOM 取得
HtmlTextInput messageText = page.getHtmlElementById("message");
// 取得した DOM(今回の場合だと input タグ)に "Hello world!" をセット
messageText.setValueAttribute(text);
// メッセージ入力画面の form を取得
HtmlForm form = page.getForms().get(0);
// メッセージ入力画面の submit を実行( MessageController#postMessage にリクエスト)
HtmlSubmitInput submit =
form.getOneHtmlElementByAttribute("input", "type", "submit");
HtmlPage newPage = submit.click();
// メッセージ確認画面( message-confirm.html )の id = "received" の DOM からテキストデータを取得
String receivedText = newPage.getHtmlElementById("received").getTextContent();
assertEquals(receivedText, text);
}
}
- (1) @ExtendWith(SpringExtension.class) について
SpringExtension.class 是从 Spring 5 开始提供的一个类,用于使 Spring TestContext Framework 能够在 JUnit 5 平台上运行。
另外,Spring TestContext Framework 是包含在 Spring Test 项目中的,可以在 JUnit、TestNG 等测试框架上使用 Spring 提供的注解、Java 标准注解和 Spring Test 提供的注解等(其他可用功能,请参考此处)。
此外,@ExtendWith 是在 JUnit 5 中提供的注解。有关 JUnit 5 的功能,请在此处查看。
我理解这句话是指在 Junit 5 平台上,使用 Spring 构建的 Web 应用程序的测试中,将使用各种必要功能的定义。
- (2) @SpringBootTest について
通过添加此注释,可以在Spring Boot环境中执行测试。有关与Spring TestContext Framework配置的区别,请参见这里 。
(我猜)这个注释会自动定义模板引擎的前缀和编码等设置。
另外,在只由控制器组成的情况下,可以使用@WebMvcTest。使用此注解可以缩短测试执行时间,因为它会缩小自动扫描的目标类范围。请参考此注解的详细说明。
- (3) WebApplicationContext について
我希望您能理解,在此我们将 DI 容器注入到外部,以使其在接下来的(4)中可以使用。
- (4) MockMvcWebClientBuilder について
这是一个用于生成依赖于MockMvc的HtmlUnit WebClient实例的构建器。在这里,我们认识到它是将DI容器中注册的各种实例与MockMvc和HtmlUnit WebClient集成在一起,以便能够使用它们进行页面获取和其他操作。接下来,我们将使用这个实例进行页面获取和其他操作。
关于未来
-
- Web API として利用されることを想定した E2E テストの手法を纏める
- Selenium WebDriver を用いた E2E テストの手法を纏める
请参考这些资料
参考这些资料
请参考参考资料
请参阅这些资料
请查阅这些资料
请参考相关资料
JUnit5 @RunWith
通过SpringExtension类的javadoc
Spring 5的Spring Test公开版本
JUnit 5用户指南
Spring Web Contexts
从E2E测试中学到的知识
HtmlUnit介绍
HtmlUnit
10.2.4. 使用OSS库进行单元测试的注解类型SpringBootTest的javadoc
Spring彻底入门,使用Spring Framework开发Java应用程序
Spring MVC Test HtmlUnit