After you have completed the unit of the data access layer, you will see how to write unit tests for service layers (services). Service layer should be the most important in the whole system, strict business logic design to ensure the stable operation of the system, so this layer of unit testing should also account for a large proportion. Although unit testing should generally be as far as possible through mock stripping dependencies, because the data access layer in the current project uses the Spring-data framework and does not contain much logic, I put the service layer and the data access layer on a pseudo unit test.
one or one-logical unit tests.
The approach used here is almost the same as the data access layer, which consists of three main steps:
1. Specify the test data set through @databasesetup
2. Execute the method of being tested
3. Query data from the database through DAO validation execution results
Suppose the code method to be tested is:
@Service @Transactional (readOnly = true) public class Shopserviceimpl extends Baseservice implements shopservice{
Ate Logger Logger = Loggerfactory.getlogger (Shopserviceimpl.class); @Transactional (readOnly = false) public Floor Addfloor (string buildingname, int floornum, String layout) {//AS
If the corresponding floor information is already present, the existing exception information is thrown Floor Floor = Floordao.findbybuildingnameandfloornum (Buildingname, floornum);
if (floor!= null) {throw new onlineshopexception (exceptioncode.shop_floor_existed);
//If no corresponding store information exists, add a new mall building building = Buildingdao.findbyname (Buildingname);
if (building = = null) {building = new building ();
Building.setname (Buildingname);
Buildingdao.save (building);
//Add and return floor information floor = new floor ();
Floor.setbuilding (building);
Floor.setfloornum (Floornum);
Floor.setmap (layout); Floordao.save (Floor);
return floor;
}
}
The corresponding interface is:
Public interface Shopservice {public
Floor Addfloor (string buildingname, int floornum, string layout);
The meaning of this logical code is very simple and straightforward, then the test of the unit to be written must include all branches: A. Store and floor information exist, throw exception B. Shopping malls exist, and floors do not exist, floor information has been added. C. Shopping malls and floors do not exist, all new. Let's take the first example and prepare the test data:
<?xml version= "1.0" encoding= "UTF-8"?>
<dataset>
<building id= "1" name= "New House"
/> <floor id= "1" building= "1" floor_num= "2"/>
</dataset>
Then write test cases, pay attention to the need for annotations can not be forgotten:
@RunWith (Springjunit4classrunner.class) @ContextConfiguration ("Classpath:applicationcontext-test.xml") @ Transactional @TestExecutionListeners ({dependencyinjectiontestexecutionlistener.class, dirtiescontexttest Executionlistener.class, Customtransactiondbunittestexecutionlistener.class, foreignkeydisabling.class}) p
Ublic class Shopservicetest {@Autowired private shopservice shopservice; @Test @DatabaseSetup ("Shop/shopservice-addfloorexistexception-dataset.xml") public void Testaddfloorexistexception () { try { Shop
Service.addfloor ("New House", 2, "");
fail (); } catch (Exception e) { asserttrue e instanceof Online
Shopexception); assertequals (ExceptionCode.Shop_Floor_Existed.code (), (OnlinEshopexception) e). GetCode ()); } }}
This test and the data Access layer test look no different.
second, using mock objects to isolate third party interfaces
Software development generally exist and third-party integration of the situation, such as the call Sina's certification, Baidu map and so on. So when writing tests, based on efficiency considerations, the general situation does not actually invoke these remote APIs (there should be other tests that can detect changes in Third-party interfaces in a timely manner), but assume that they always return the expected results. Mock objects need to be used at this time to simulate these APIs to produce the corresponding results.
Here, I use the Mockito, it is very convenient to use. If the user is now logged in, need to go to the Third-party system verification, then now see how to test this scenario. Let's take a look at the test method first:
Private Boolean ValidateUser (String inputname, String inputpassword) {return
thirdpartyapi.authenticate ( InputName, Inputpassword);
Where Thirdpartyapi is the API that the third party uses to authenticate. Let's look at the test code:
public class Userservicetest {
@Autowired
private userservice userservice;
Private Thirdpartyapi Mockthirdpartyapi = mock (thirdpartyapi.class);
@Test public
void Testlogin () {
//Specifies the return result of a mock object-specific action when
(Mockthirdpartyapi.authenticate ("Jiml", "Ji ML)). Thenreturn (true);
Replaces third party dependencies ((Userserviceimpl) userservice) initialized by spring by a setter with a mock object
. Setthirdpartyapi (MOCKTHIRDPARTYAPI);
Boolean loginstatus = Userservice.login ("Jiml", "Jiml");
Asserttrue (loginstatus);
}
}
In fact, the service layer test does not have too many new things, and the most critical question is how the logic of each branch can be tested, so that the test really played for the software quality escort role.