《Spring Boot in Action》【4. 测试】
来源:互联网 发布:求补码的方法编程 编辑:程序博客网 时间:2024/06/06 00:48
4. 测试
4.1 集成测试
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = AddressBookConfiguration.class)public class AddressServiceTests { @Autowired private AddressService addressService; @Test public void testService() { Address address = addressService.findByLastName("Sheman"); assertEquals("P", address.getFirstName()); // ... }}
SpringJUnit4ClassRunner类用来启用Spring集成测试,它是一个加载Spring应用上下文和在测试类中启用自动注入的JUnit类运行器(从Spring 4.2起,你也可以使用SpringClassRule和SpringMethodRule这种基于规则的替换方案),@ContextConfiguration指定了如何加载Spring应用上下文。
不过Spring Boot应用是由SpringApplication加载的(或SpringBootServletInitializer),它不仅加载应用上下文,还启用日志,加载外部配置文件等Spring Boot特性,但是如果使用@ContextConfiguration,这些特性是没有的,所以一般是使用Spring Boot的@SpringApplicationConfiguration来替换@ContextConfiguration,它会像SpringApplication那样。
4.2 测试Web应用
测试Web应用,有两个选择:
- Spring Mock MVC——模拟一个Servlet容器来测试Controller
- Web集成测试——在内置Servlet容器(Tomcat或Jetty)中启动应用来测试
Spring Mock MVC
@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes = ReadingListApplication.class)@WebAppConfigurationpublic class MockMvcWebTests { @Autowired private WebApplicationContext webContext; private MockMvc mockMvc; @Before public void setupMockMvc() { mockMvc = MockMvcBuilders .webAppContextSetup(webContext) .build(); }}
测试HTTP GET请求
@Testpublic void homePage() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/readingList")) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.view().name("readingList")) .andExpect(MockMvcResultMatchers.model().attributeExists("books")) .andExpect(MockMvcResultMatchers.model().attribute("books", Matchers.is(Matchers.empty())));}
加入静态引入,可以更简洁:
import static org.hamcrest.Matchers.*;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;@Testpublic void homePage() throws Exception { mockMvc.perform(get("/readingList")) .andExpect(status().isOk()) .andExpect(view().name("readingList")) .andExpect(model().attributeExists("books")) .andExpect(model().attribute("books", is(empty())));}
测试HTTP POST请求,添加一本书:
@Testpublic void postBook() throws Exception { mockMvc.perform(post("/readingList") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .param("title", "BOOK TITLE") .param("author", "BOOK AUTHOR") .param("isbn", "1234567890") .param("description", "DESCRIPTION")) .andExpect(status().is3xxRedirection()) .andExpect(header().string("Location", "/readingList")); Book expectedBook = new Book(); expectedBook.setId(1L); expectedBook.setReader("craig"); expectedBook.setTitle("BOOK TITLE"); expectedBook.setAuthor("BOOK AUTHOR"); expectedBook.setIsbn("1234567890"); expectedBook.setDescription("DESCRIPTION"); mockMvc.perform(get("/readingList")) .andExpect(status().isOk()) .andExpect(view().name("readingList")) .andExpect(model().attributeExists("books")) .andExpect(model().attribute("books", hasSize(1))) .andExpect(model().attribute("books", contains(samePropertyValuesAs(expectedBook))));}
测试安全性:
引入包:
testCompile("org.springframework.security:spring-security-test")
然后加一行:
@Beforepublic void setupMockMvc() { mockMvc = MockMvcBuilders .webAppContextSetup(webContext) .apply(springSecurity()) .build();}
springSecurity()是SecurityMockMvcConfigurers的一个静态方法,它会遵照你的安全配置。
@Testpublic void homePage_unauthenticatedUser() throws Exception { mockMvc.perform(get("/")) .andExpect(status().is3xxRedirection()) .andExpect(header().string("Location", "http://localhost/login"));}
如何测试一个通过认证的请求?Spring Security提供两个注解:
- @WithMockUser——加载一个UserDetails,使用指定的用户名、密码和权限
- @WithUserDetails——根据指定的用户名查找一个UserDetails对象并加载
@Test@WithMockUser(username="craig", password="password", roles="READER")public void homePage_authenticatedUser() throws Exception { ...}
@WithUserDetails注解使用配置好的UserDetailsService来加载UserDetails对象:
@Test@WithUserDetails("craig")public void homePage_authenticatedUser() throws Exception { Reader expectedReader = new Reader(); expectedReader.setUsername("craig"); expectedReader.setPassword("password"); expectedReader.setFullname("Craig Walls"); mockMvc.perform(get("/")) .andExpect(status().isOk()) .andExpect(view().name("readingList")) .andExpect(model().attribute("reader", samePropertyValuesAs(expectedReader))) .andExpect(model().attribute("books", hasSize(0)))}
测试运行中的应用
Spring Boot’s @WebIntegrationTest注解,不仅可以创建一个应用上下文,还可以启动内置Servlet容器。
@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes = ReadingListApplication.class)@WebIntegrationTestpublic class SimpleWebTest { @Test(expected = HttpClientErrorException.class) public void pageNotFound() { try { RestTemplate rest = new RestTemplate(); rest.getForObject("http://localhost:8080/bogusPage", String.class); fail("Should result in HTTP 404"); } catch (HttpClientErrorException e) { assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode()); throw e; } }}
默认启动8080端口,你可以设置如下之一来选择随机端口:
@WebIntegrationTest(value={"server.port=0"})@WebIntegrationTest("server.port=0")@WebIntegrationTest(randomPort=true)
现在端口是随机了,但是如何获取这个端口呢?你可以注入进来:
@Value("${local.server.port}")private int port;rest.getForObject("http://localhost:{port}/bogusPage", String.class, port);
使用Selenium测试HTML页面
Selenium启用浏览器来测试,就像手工测试一样,不过它可以自动化和重复执行,首先添加包:
testCompile("org.seleniumhq.selenium:selenium-java:2.45.0")
测试样例:
@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes=ReadingListApplication.class)@WebIntegrationTest(randomPort=true)public class ServerWebTests { private static FirefoxDriver browser; @Value("${local.server.port}") private int port; @BeforeClass public static void openBrowser() { browser = new FirefoxDriver(); browser.manage().timeouts() .implicitlyWait(10, TimeUnit.SECONDS); } @AfterClass public static void closeBrowser() { browser.quit(); } @Test public void addBookToEmptyList() { String baseUrl = "http://localhost:" + port; browser.get(baseUrl); assertEquals("You have no books in your book list", browser.findElementByTagName("div").getText()); browser.findElementByName("title").sendKeys("BOOK TITLE"); browser.findElementByName("author").sendKeys("BOOK AUTHOR"); browser.findElementByName("isbn").sendKeys("1234567890"); browser.findElementByName("description").sendKeys("DESCRIPTION"); browser.findElementByTagName("form").submit(); WebElement dl = browser.findElementByCssSelector("dt.bookHeadline"); assertEquals("BOOK TITLE by BOOK AUTHOR (ISBN: 1234567890)", dl.getText()); WebElement dt = browser.findElementByCssSelector("dd.bookDescription"); assertEquals("DESCRIPTION", dt.getText()); }}
- 《Spring Boot in Action》【4. 测试】
- Spring-boot IN Action(1)
- 《Spring Boot in Action》【1. 起步】
- 《Spring Boot in Action》【3. 自定义配置】
- 《Spring Boot in Action》【5. Groovy】
- 《Spring Boot in Action》【6. Grails】
- 《Spring Boot in Action》【7. Actuator】
- 《Spring Boot in Action》【8. 部署】
- 《Spring Boot in Action》【A. 开发者工具】
- spring in action 测试例子失败
- 《Spring Boot in Action》【2. 开发第一个应用】
- Spring in action 读书笔记
- Spring in action
- Spring in Action
- Spring in Action
- Spring in action笔记
- 读书笔记:spring in action
- Spring in Action问题
- JAVA提高一:静态导入、可变参数、增强型for循环、装拆箱
- 学习各种语言初级知识语法了解
- org.asynchttpclient.AsyncHttpClient
- ubuntu1604 server安装及图形界面安装
- POI 设置单元格背景色,背景色编码与实际颜色对照表
- 《Spring Boot in Action》【4. 测试】
- winform将listview数据导出到excel中
- hitTest和pointInside方法你真的熟吗?
- css3弹性盒模型flex快速入门与上手1
- JavaScript匿名自执行函数的定义
- 基于主动学习的高光谱图像分类方法研究
- Django中的一些常用内置函数
- JavaScript的封装
- [VS2010]_[Windows]_[Debug模式下LoadLibrary错误87]