Web集成测试允许对Spring Boot应用程序进行集成测试,而无需进行任何模拟。 通过使用@WebIntegrationTest
和@SpringApplicationConfiguration
我们可以创建加载应用程序并在普通端口上侦听的测试。 Spring Boot的这一小增加使使用Selenium WebDriver创建集成测试变得更加容易。
测试依赖
我们将要测试的应用程序是一个简单的Spring Boot / Thymeleaf应用程序,具有spring-boot-starter-web
, spring-boot-starter-thymeleaf
和spring-boot-starter-actuator
依赖性。 请参阅参考资料以获取GitHub项目的链接。
测试依赖项为:
org.springframework.boot
spring-boot-starter-test
test
org.assertj
assertj-core
1.5.0
test
org.seleniumhq.selenium
selenium-java
2.45.0
test
网络集成测试
在经典的Spring Test中,使用MockMvc
可以创建如下的测试:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class HomeControllerClassicTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void verifiesHomePageLoads() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
}
@SpringApplicationConfiguration
扩展了@ContextConfiguration
功能,并加载应用程序上下文以进行集成测试。 要创建没有@WebIntegrationTest
环境的测试,我们应该使用@WebIntegrationTest
批注定义测试:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebIntegrationTest(value = "server.port=9000")
public class HomeControllerTest {
}
这将在JUnit测试中启动完整的应用程序,监听端口9000
。 有了这样的测试,我们可以轻松地使用浏览器添加Selenium并执行实际的功能测试(除非使用HtmlUnit驱动程序,否则在无头环境中将无法工作–但这不在本文的讨论范围之内)。
添加硒
将Selenium添加到测试中非常简单,但是我想实现的目标还不止于此,因此我创建了一个自定义批注,将我的测试标记为Selenium测试。 我还以允许将WebDriver
注入测试实例的方式配置了它:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebIntegrationTest(value = "server.port=9000")
@SeleniumTest(driver = ChromeDriver.class, baseUrl = "http://localhost:9000")
public class HomeControllerTest {
@Autowired
private WebDriver driver;
}
@SeleniumTest
是一个自定义注释:
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@TestExecutionListeners(
listeners = SeleniumTestExecutionListener.class,
mergeMode = MERGE_WITH_DEFAULTS)
public @interface SeleniumTest {
Class extends WebDriver> driver() default FirefoxDriver.class;
String baseUrl() default "http://localhost:8080";
}
注释使用添加了测试执行侦听器,该侦听器将创建可在集成测试中使用的WebDriver
实例。 TestExecutionListener
定义了一个侦听器API,用于对测试执行事件做出反应。 它可以用于测试。 例如,Spring Test中的示例实现用于支持测试管理的事务或将依赖项注入到测试实例中。
TestExecutionListener
注意:为了更好的可读性, SeleniumTestExecutionListener
的代码的某些部分被跳过。
SeleniumTestExecutionListener
提供了将配置的WebDriver
注入测试实例的方法。 该驱动程序实例仅创建一次,并且可以使用@SeleniumTest
批注简单地更改所使用的驱动程序。 最重要的是在Bean Factory中注册驱动程序。
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
ApplicationContext context = testContext.getApplicationContext();
if (context instanceof ConfigurableApplicationContext) {
SeleniumTest annotation = findAnnotation(
testContext.getTestClass(), SeleniumTest.class);
webDriver = BeanUtils.instantiate(annotation.driver());
// register the bean with bean factory
}
}
在使用WebDriver
打开应用程序的每个测试方法的基本URL之前,请执行以下操作:
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
SeleniumTest annotation = findAnnotation(
testContext.getTestClass(), SeleniumTest.class);
webDriver.get(annotation.baseUrl());
}
另外,在每次失败时都会生成一个屏幕截图:
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
if (testContext.getTestException() == null) {
return;
}
File screenshot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);
// do stuff with the screenshot
}
每次测试后,驱动程序将关闭:
@Override
public void afterTestClass(TestContext testContext) throws Exception {
if (webDriver != null) {
webDriver.quit();
}
}
这只是一个例子。 实现非常简单。 我们可以扩展注释和侦听器的功能。
考试
运行以下测试将启动Chrome浏览器并使用Selenium执行一些简单的检查:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebIntegrationTest(value = "server.port=9000")
@SeleniumTest(driver = ChromeDriver.class, baseUrl = "http://localhost:9000")
public class HomeControllerTest {
@Autowired
private WebDriver driver;
private HomePage homePage;
@Before
public void setUp() throws Exception {
homePage = PageFactory.initElements(driver, HomePage.class);
}
@Test
public void containsActuatorLinks() {
homePage.assertThat()
.hasActuatorLink("autoconfig", "beans", "configprops", "dump", "env", "health", "info", "metrics", "mappings", "trace")
.hasNoActuatorLink("shutdown");
}
@Test
public void failingTest() {
homePage.assertThat()
.hasNoActuatorLink("autoconfig");
}
}
该测试使用带有自定义AssertJ断言的简单页面对象。 您可以在GitHub中找到完整的源代码。 请参阅参考资料。
如果发生故障,驱动程序拍摄的屏幕快照将存储在适当的目录中。
摘要
@WebIntegrationTest
和@SpringApplicationConfiguration
批注,可以在常规JUnit测试中对完全加载的Spring Boot应用程序进行集成测试。 使应用程序在测试中运行将为您提供使用Selenium并使用浏览器运行功能测试的可能性。 如果将其与Profile和Spring Test的其他功能(例如@Sql
, @SqlConfig
) @Sql
, @SqlConfig
可能会为集成测试提供功能强大而简单的解决方案。
参考文献
- 源代码: https : //github.com/kolorobot/spring-boot-thymeleaf
- Spring Boot测试: http : //docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing
- Spring测试: http : //docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html
翻译自: https://www.javacodegeeks.com/2015/03/spring-boot-integration-testing-with-selenium.html