One, test the Web application
To properly test a Web application, you need to put in some actual HTTP requests, confirming that it handles those requests correctly. Spring boot developers have two options to implement this type of test:
- Spring Mock MVC: The ability to test the controller in an approximate real-world analog servlet container without actually starting the application server.
- Web integration testing: Launch applications in an embedded servlet container (such as Tomcat or jetty) and perform tests on a real application server.
1. Simulating Spring MVC
To set up mock MVC in a test, you can use Mockmvcbuilders, which provides two static methods:
- Standalonesetup (): Constructs a mock MVC that provides one or more controllers that are manually created and configured.
- Webappcontextsetup (): Uses the spring application context to build mock MVC, which can contain one or more configured controllers.
Two method differences:
- Standalonesetup (): Manually Initialize and inject the controller to be tested,
- Webappcontextsetup (): Based on an instance of Webapplicationcontext, typically loaded by spring.
The former is closer to unit testing, and you might just want to focus on testing a single controller, which lets spring load the controller and its dependencies for complete integration testing.
/* Code Listing 4-2 creating mock MVC for the Integration test controller */@RunWith (Springjunit4classrunner.class) @SpringApplicationConfiguration (classes = readinglistapplication.class) //open the Web context @WebAppConfiguration public Span class= "Hljs-class" >class mockmvcwebtests { @Autowired private webapplicationcontext webcontext; //injection webapplicationcontext private mockmvc mockmvc; @Before public void setupmockmvc () {MOCKMVC = Mockmvcbuilders. Webappcontextsetup (webcontext) //set MOCKMVC. Build ();}}
/* 向/readingList发起一个GET请求 */@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())));}
/* Initiate a POST request to/readinglist */@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"));
/* Verify the POST request just now */Configure the desired book Expectedbook = new book (); Expectedbook.setid (1l) expectedbook.setreader ( "Craig"); Expectedbook.settitle ( "book TITLE") Expectedbook.setauthor ( "DESCRIPTION"); //performs a GET request 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)))}
2. Test Web Security
Using Spring Security
Add dependency
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope></dependency>
Using the Spring Security configurator when creating MOCKMVC instances
@Beforepublic void setupMockMvc() { mockMvc = MockMvcBuilders .webAppContextSetup(webContext) .apply(springSecurity()) .build();}
Use (the specific security configuration depends on how you configure spring security (or how spring boot automatically configures spring security). )
Scene Code:
1) Request for unauthenticated authentication
/* 请求未经身份验证,重定向回登录界面 */@Testpublic void homePage_unauthenticatedUser() throws Exception { mockMvc.perform(get("/")) .andExpect(status().is3xxRedirection()) .andExpect(header().string("Location", "http://localhost/login"));}
2) Request Authenticated Spring Security provides two annotations:
- @WithMockUser: Creates a Userdetails object with the given value, specifying the user name, password, and authorization.
- @WithUserDetails: Loads the Userdetails object using a pre-configured Userdetailsservice to find and return a reader object based on the given user name.
/* 经过身份验证的请求,使用@WithMockUser */@Test@WithMockUser(username="craig", password="password", roles="READER") public void homePage_authenticatedUser() throws Exception { ...}
/* Authenticated request, use @withuserdetails */@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 ( "readinglist")). Andexpect (Model (). Attribute ( "reader", Samepropertyvaluesas (Expectedreader)). Andexpect (Model (). Attribute ( "books", Hassize ( Span class= "Hljs-number" >0))}
The servlet container is not started here to run these tests, and spring's mock MVC replaces the actual servlet container. It is better than calling the Controller method directly, but it does not actually execute the application in a Web browser, validating the rendered view.
III. application in Test run
Spring boot supports the use of an embedded servlet container to launch an application.
This is what Spring Boot's @WebIntegrationTest annotations do. Adding @webintegrationtest annotations on a test class can state that you want spring boot not only to create an application context for the test, but also to launch an embedded servlet container. Once the application is running in an embedded container, you can initiate a real HTTP request and assert the result.
/* Code Listing 4-5 launches the application in the server and initiates an HTTP request to the application in spring Resttemplate */@RunWith (Springjunit4classrunner.class)@SpringApplicationConfiguration (Classes=readinglistapplication.class)@WebIntegrationTestPublic class simplewebtest { @Test (expected=httpclienterrorexception.class) public void Pagenotfound() { try {resttemplate rest = new Resttemplate (); Rest.getforobject ( c13> "Http://localhost:8080/bogusPage", String.class); Fail ("should result in HTTP 404");} catch (Httpclienterrorexception e) {assertequals (Httpstatus.not_found, E.getstatuscode ()); throw e;} } }
1. Start the server with a random port
@WebIntegrationTest(value={"server.port=0"})
or @WebIntegrationTest("server.port=0")
maybe @WebIntegrationTest(randomPort=true)
Using ports
@Value("${local.server.port}")private int port;
rest.getForObject("http://localhost:{port}/bogusPage", String.class, port);
2. Using selenium to test HTML pages
Add Org.seleniumhq.selenium Dependency
Used in the Code
1> Configuration
/* Use the Selenium test template in spring boot */@RunWith (Springjunit4classrunner.class)@SpringApplicationConfiguration (Classes=readinglistapplication.class)@WebIntegrationTest (randomport=TruePublicClassserverwebtests {Privatestatic Firefoxdriver browser;@Value ( "${local.server.port}") private int port; //configure Firefox driver @BeforeClass public static void openbrowser () {browser = new firefoxdriver (); Browser.manage (). Timeouts (). implicitlywait (10, Timeunit.seconds);} //Close browser @AfterClass public static void closebrowser () {browser.quit ();}
2> Test
Test the reading list application with Selenium@TestPublicvoidAddbooktoemptylist() {String BASEURL ="http://localhost:" + port; Browser.get (BASEURL); Assertequals ("You had no books in your book list", Browser.findelementbytagname ("Div"). GetText ());Populate and send form Browser.findelementbyname ("title"). SendKeys ( "book TITLE"); Browser.findelementbyname ( "author"). SendKeys ( "book author") ; Browser.findelementbyname ( "ISBN"). SendKeys ( "1234567890"); Browser.findelementbyname ( "description"). SendKeys ( "form"). Submit (); //determine if the list contains a new book webelement dl = Browser.findelementbycssselector ( "Dt.bookheadline"); Assertequals ( "book TITLE by Book AUTHOR (isbn:1234567890)", Dl.gettext ()); Webelement dt = browser.findelementbycssselector ( "DESCRIPTION", Dt.gettext ()); }
Note: The version of the book is older, the following additions to the new version of the test method. An example is excerpted from Segmentfault_chenatu's article (only after the Spring-boot 1.4 version):
Directly call the interface function to test:
@RunWith(SpringRunner.class)@SpringBootTestpublic class ApiTest { @Autowired MessageApi messageApi; ...
Test controller:
@RunWith (Springrunner.class)@SpringBootTest@AutoConfigureMockMvcPublicClasscontrollertest { @Autowired private mockmvc mockmvc; @Test public void testcontrollermethods () {Mvcresult result = Mockmvc.perform (Get ( "/get-receive-message-abstracts"). Param ( "SiteId", Span class= "hljs-string" > "webtrn"). Param ( "UID", "Lucy"). Param ( "limit", "$", Hassize (10)). Andexpect (JsonPath "$[9].title", is ( "Hello0")). Andreturn (); }
Spring Boot Web Unit test program