JUnit test controller (MOCKMVC used), Transport @requestbody Data solutions

Source: Internet
Author: User
Tags rollback log4j

The purpose of unit testing

In short, it's a test of all the logic after we add or change some code, especially after we've modified it (whether it's adding new features, modifying bugs), and we can do it again . To reduce the recurrence of problems that we have solved even before they were released.

This is mainly done by using MOCKMVC to unit test the controller of our system.

The operation of the database using transaction implementation rollback, and the database additions and deletions after the end of the database will also be far.

Second, the use of MOCKMVC

1, first of all, our last example,

Import Org.apache.commons.logging.Log;
Import Org.apache.commons.logging.LogFactory;
Import Org.junit.Before;
Import Org.junit.runner.RunWith;
Import org.springframework.beans.factory.annotation.Autowired;
Import Org.springframework.http.MediaType;
Import org.springframework.test.context.ContextConfiguration;
Import Org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
Import org.springframework.test.context.transaction.TransactionConfiguration;
Import org.springframework.test.context.web.WebAppConfiguration;
Import ORG.SPRINGFRAMEWORK.TEST.WEB.SERVLET.MOCKMVC;
Import Org.springframework.test.web.servlet.RequestBuilder;
Import org.springframework.test.web.servlet.ResultActions;
Import Org.springframework.test.web.servlet.setup.MockMvcBuilders;
Import org.springframework.transaction.annotation.Transactional;

Import Org.springframework.web.context.WebApplicationContext;
Import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; Import Static ORG.SPRingframework.test.web.servlet.request.MockMvcRequestBuilders.post;
Import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;

Import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 /** * Created by Zhengcanrui on 16/8/11. * * @RunWith (Springjunit4classrunner.class) @ContextConfiguration (locations={"classpath:spring/ Applicationcontext-*xml "}"///Configure transaction rollback, the deletion of the database will be rolled back, to facilitate the use of test case recycling @TransactionConfiguration (TransactionManager = " TransactionManager ", Defaultrollback = True) @Transactional @WebAppConfiguration public class Test {//Remember configuration Log4j.prop

    erties, the command line output level is debug protected Log logger= Logfactory.getlog (testbase.class);

    protected MOCKMVC Mockmvc;

    @Autowired protected Webapplicationcontext WAC; @Before ()//This method executes the public void Setup () {MOCKMVC = Mockmvcbuilders.webappcontextsetup (WAC) before each method executes. Build  (); Initializes the Mockmvc object} @org. junit.test public void getallcategorytest () thRows Exception {String responsestring = Mockmvc.perform (Get ("/categories/getallcategory")//Please The requested method is the format of the Get. ContentType (mediatype.application_form_urlencoded)//data. param         ("Pcode", "root")//Add parameters). Andexpect (Status (). IsOk ())//Return status is Anddo (print ())   Print out the request and the corresponding content. Andreturn (). GetResponse (). getcontentasstring ();
    Converts the corresponding data to a string System.out.println ("--------json =" + responsestring); }

}

The testing of Spring MVC often seems more complex. In fact, his difference is that he needs a servletcontext to simulate our requests and responses. But spring also provides a mock test interface for the request and response of spring MVC to make our unit test coverage more than just the Service,dao layer.

2, Code Explanation:

@webappconfiguration is a level of comment that declares a applicationcontext integration test load Webapplicationcontext. function is to simulate ServletContext

@ContextConfiguration: Because Controller,component and so on are using annotations, you need to specify spring's configuration file, scan the appropriate configuration, initialize the class, and so on.

@TransactionConfiguration (TransactionManager = "TransactionManager", Defaultrollback = True)
@Transactional

The effect of the above two sentences is to let our operations on the database roll back, such as adding operations to the database, which will undo our operation of the database after the method is finished.

Why do I need a transaction rollback? The test process on the database operation, will produce dirty data, affecting the correctness of our data is not convenient cycle test, that is, if we delete a record, the next time we can not do this junit test, because the record has been deleted, will be an error. If you do not use transaction rollback, we need to explicitly restore our additions and deletions to the database operation in our code, and we will have a lot more to do with test-independent code

Method Resolution: perform: executes a requestbuilder request , automatically executes the SPRINGMVC process and maps to the appropriate controller to perform the processing ; get: Declares a method that sends a GET request. Mockhttpservletrequestbuilder Get (String urltemplate, Object ... urlvariables): The URI template and the URI variable are worth the way of the request. Additional requests are provided, such as post, put, delete, and so on. param: Add the parameters of the request, such as the Pcode = root parameter when sending the requests above. If you use a format that requires sending JSON data , you will not be able to use this method, which can be seen as a workaround for the @responsebody annotation parameters later andexpect : Add Resultmatcher validation Rules to verify that the results are correct after the controller has been executed (judgment of the returned data); anddo: Add Resulthandler result processor, For example, when debugging print results to the console (the return of the data); Andreturn: Finally return the corresponding Mvcresult; then perform custom validation/next asynchronous processing (the judgment of the returned data);

Note: The use of log4j on the Mac is, if the use of ${catalina.home} need attention, Mac will not find the path to Tomcat, directly back to the root path "/", and normally, the root path is not write permission, you need to use Administrator to assign permissions. Log4j after the configuration is complete, you need to set the level of the print log, and if not set, the log will not print in JUnit.

3, back in the background of the data, it is best to take our database modified results returned to the front-end.

Why to return a modified or added object in data to return the data to the front end, the front-end easy to determine whether the data added or modify the successful update or add the data often need to refresh the page, the data directly to the front end, the front end without sending a request to get unit test, When we can do the DDL (add-in) operation of the database, we can audit the data and how to judge whether our operation is successful or not. As in the following example:

We send an add operation, add a Softinfo object, and the Softinfo class is defined as follows:

public class Softinfo {
    private String ID;
    private String name;

After the addition, because we have the transaction rollback of unit test, we will not be able to see the database of our add operations, can not determine the success of the operation.

To solve the problem above, we can add a "data" field to the returned JSON data and parse the data field in the JSON to determine if our add operation was successful. The JSON format is as follows:

{"
    status": "
    Data": {"id": "2", "Name": "Test"}
}

We can use the Andexpect method to judge the returned data, using "$. Attribute" To get the data inside, as I want to get the "Data.name" in the return data, I can write "$.data.name". The following example is the Data.name= "test" to determine the return.

@Test public
    void Testcreateseewoaccountuser () throws Exception {
        mockmvc.perform (post ("/users")
                        . ContentType (mediatype.application_form_urlencoded)  
        ). Andexpect (Status (). IsOk ())
        . Andexpect (Jsonpath ("$ . Data.name ", Is (" Test ")))  
        . Andexpect (Jsonpath (" $.data.createtime ", Notnullvalue ())
        ;
    }

Iii. problems encountered

1, send a @responsebody identified by the parameters, until 400 error. That is, you cannot send a JSON-formatted data to the controller layer.

Workaround 1:

      Softinfo softinfo = new Softinfo ();
Set Value
objectmapper mapper = new Objectmapper ();
        Objectwriter ow = Mapper.writer (). Withdefaultprettyprinter ();
        Java.lang.String Requestjson = ow.writevalueasstring (softinfo);
        String responsestring = Mockmvc.perform (Post ("/softs"). ContentType (mediatype.  Application_json). Content (Requestjson)). Anddo (print ())
                . Andexpect (Status (). IsOk ()). Andreturn (). GetResponse (). getcontentasstring ();

Workaround 2: Convert an object to JSON data using Com.alibaba.fastjson.JSONObject

Softinfo softinfo = new Softinfo ();
。。。 Set Value
String Requestjson = jsonobject.tojsonstring (folderinfo);
        String responsestring = Mockmvc.perform (Post ("/softs"). ContentType (Mediatype.application_json). Content ( Requestjson)). Anddo (print ()).
                Andexpect (Status (). IsOk ()). Andreturn (). GetResponse (). getcontentasstring ();

Note that the above contenttype needs to be set to Mediatype.application_json, that is, the declaration is sent "Application/json" format data. Using the content method, put the converted JSON data into the body of the request.

2, Java.lang.noclassdeffounderror:com/jayway/jsonpath/invalidpathexception

The jar package is missing:

Can add a bit of maven dependencies

<dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactid>json-path</ artifactid>
            <version>0.8.1</version>
            <scope>test</scope>
        </ dependency>
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            < artifactid>json-path-assert</artifactid>
            <version>0.8.1</version>
            <scope> Test</scope>
        </dependency>

Learning Links: https://www.petrikainulainen.net/spring-mvc-test-tutorial/

   Thanks: Thank you for your reading.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.