In the "programmers who don't write unit tests are not good programmers" principle, I'm sticking with the unit test, not saying that all Java Web applications are based on spring, but at least more than half are spring-based. After discovering bean management through spring, there are a variety of deficiencies in testing
For example, when many people do unit tests, they also initialize the spring container in the Before method, causing the container to be initialized multiple times.
[Java]View PlainCopyPrint?
- @Before
- public void init () {
- applicationcontext ctx = new Filesystemxmlapplicationcontext ( "Classpath:spring/spring-basic.xml" );
- basedao = (Ibasedao) ctx.getbean ( );
- assertnotnull (Basedao);
- }
@Before public void init () { ApplicationContext ctx = new Filesystemxmlapplicationcontext ("classpath:spring/ Spring-basic.xml "); Basedao = (Ibasedao) ctx.getbean ("Basedao"); Assertnotnull (Basedao); }
When developing spring-based applications, if you also use JUnit for unit testing, you miss the most important hard dish in spring feast.
Before we go into this dish, let's talk about the problem of using JUnit directly for unit testing in a spring-based Javaweb project.
1) causes multiple spring container initialization problems
Depending on the invocation process of the JUnit test method, each test method executes creates an instance of the test case and calls the Setup () method. As a general rule, we initialize the spring container in the Setup () method, which means that if there are many test methods for the test case, the spring container is repeatedly initialized multiple times. Although it is not too slow to initialize the spring container, it is possible to perform time-consuming operations such as loading the hibernate mapping file when the spring container is initialized, and if the spring container must be initialized repeatedly for each test method, the impact on the performance of the test is not negligible;
With the spring test suite, the spring container is initialized only once!
2) require a hard-coded way to get the bean manually
In the test case class we need to get the target bean that needs to be tested from the SPIRNG container through the Ctx.getbean () method, and also perform a styling operation that enforces the type conversion. This tedious operation mist in the code of the test case, which makes people feel cumbersome;
Using the Spring test suite, the properties in the test case class are automatically populated with the corresponding bean for the spring container
, you do not need to set bean! manually
3) database site vulnerable to damage
Test method changes to the database are persisted to the database. Although it is for the development database, it may affect the subsequent test behavior if the impact of the data operation is persistent. For example, the user inserts a user record with ID 1 in the test method, and the first run will not have a problem, and the second run will cause the test case to fail because of a primary key violation. Therefore, it should be able to complete the functional logic check, but also can restore the scene after the test is completed, will not leave "Sequela";
With the spring test suite, spring will automatically roll back the operation of the database after you validate it, ensuring that the database is not destroyed, so there is no problem with duplicate testing!
4) Inconvenient to check the correctness of data operation
If we insert a successful login log into the log table, we do not check whether a record is actually added to the T_login_log table. In general, we may open the database and visually observe if the corresponding record is inserted, but this is a serious violation of the principle of automated testing. Imagine how to check with the naked eye when testing a program that includes thousands of data manipulation behaviors.
As long as you inherit the use case class of the spring test suite, you can access the database through JdbcTemplate in the same transaction, query the data changes, verify the correctness of the operation!
After reading the above, I believe you already know what I mean by the hard dish.
Let's look at how the code becomes elegant after using the Spring test suite. 1. Join the dependency package
Using Spring's test framework requires adding the following dependency packages :
- JUnit 4
- Spring Test (Test package in spring framework)
- Spring related other dependencies (no more, it's the context package)
If you use MAVEN, add the following dependencies in your spring-based project:
[HTML]View PlainCopyPrint?
- < Dependency >
- < groupId > JUnit </ groupId >
- < Artifactid > JUnit </ Artifactid >
- < version > 4.9 </ version >
- < Scope > Test </ Scope >
- </ Dependency >
- < Dependency >
- < groupId > org.springframework </ groupId >
- < Artifactid > spring-test </ Artifactid >
- < version > 3.2.4.RELEASE </ version >
- < Scope > provided </ Scope >
- </ Dependency >
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> < dependency> <groupId>org.springframework</groupId> <artifactid>spring-test</ artifactid> <version> 3.2.4.RELEASE </version> <scope>provided</scope>
2. Create test source catalogs and packages
Here, it is recommended to create a source file directory with SRC peers, because the classes within SRC are prepared for future products, and the classes here are for testing purposes only. and the name of the package can be the same as the directory in SRC, so because in the test source directory, so there is no conflict, and the name is identical, more convenient to retrieve. This is also the MAVEN agreement.
3. Create a test class
1) The base class is actually used to load the configuration file
[Java]View PlainCopyPrint?
- @RunWith (Springjunit4classrunner. class ) //Use JUNIT4 for testing
- @ContextConfiguration
- ({"/spring/app*.xml","/spring/service/app*.xml"}) //Load configuration file
- //------------If you add the following code, all test classes that inherit the class will follow that configuration, or not, on the test class's method///control transaction, see next instance
- //This is very important, if you do not add this annotation configuration, transaction control will be completely invalid!
- //@Transactional
- // The transaction here is associated to the transaction controller in the configuration file (TransactionManager = "TransactionManager"), and//specifies an automatic rollback (Defaultrollback = true). The data in this operation will not pollute the database!
- //@TransactionConfiguration (TransactionManager = "TransactionManager", Defaultrollback = True)
- //------------
- Public class basejunit4test {
- }
@RunWith (Springjunit4classrunner.class) //Use JUNIT4 for test @contextconfiguration ({"/spring/app*.xml", "/spring/ Service/app*.xml "})//Load profile//------------If you add the following code, all test classes that inherit the class will follow that configuration, or not, on the test class's method///control transaction, see next instance//This is very critical, If you do not add this annotation configuration, the transaction control will be completely invalidated! @Transactional//Transactions here are associated to the transaction controller in the configuration file (TransactionManager = "TransactionManager"), and//Specify automatic rollback (Defaultrollback = true). The data in this operation will not pollute the database! @TransactionConfiguration (TransactionManager = "TransactionManager", Defaultrollback = True)//------------Public Class Basejunit4test {}
2 ) followed by our own test class
[Java]View PlainCopyPrint?
- Public class userassignservicetest extends basejunit4test{
- @Resource //auto-injection, default by name
- Private Ibasedao Basedao;
- @Test //Marked as test method
- @Transactional //indicate that this method requires the use of transactions
- @Rollback (false) //Indicates that the transaction does not roll back after using this method, and true is a rollback
- Public void Insert () {
- String sql="insert into User (Name,password) VALUES (?,?)" ;
- Object[] objs=new object[]{"xx","the"};
- Basedao.insert (SQL, OBJS);
- String sql1="SELECT * from user where name=? and password=? ";
- List<map<string,object>> list=basedao.queryforlist (SQL1, OBJS);
- SYSTEM.OUT.PRINTLN (list);
- Asserttrue (List.size () >0);
- }
- }
public class Userassignservicetest extends basejunit4test{ @Resource //Auto injection, default by name private Ibasedao Basedao; @Test //Indicates the test method @Transactional //Indicates that this method requires a transaction @Rollback (FALSE) //indicates that the transaction does not roll back after using this method, and true is a rollback Public void Insert () { String sql= ' insert into user (Name,password) VALUES (?,?) "; Object[] objs=new object[]{"xx", "to"}; Basedao.insert (SQL, OBJS); String sql1= "SELECT * from user where name=? and password=? "; List<map<string,object>> list=basedao.queryforlist (SQL1, OBJS); SYSTEM.OUT.PRINTLN (list); Asserttrue (List.size () >0);} }
Next time, let's talk about it. Use the JUnit test suite to further streamline testing and repetitive work.
Chat Unit Test (iii)--spring Test+junit perfect combination