When we test a particular type, since it occurred with other types of contact, so often the source of such tests will also be in contact with the class also tested. This test, the test will be directly dependent on the type of other types, if other types of change being tested also be forced to change category. More importantly, these other types may not have been tested, it is necessary to test these classes can be tested by test category. This case, the test Development ring hollow. And if others also cited the category being tested, we test which in the end a class? Thus, in testing, if we can isolate being tested categories, it does not depend on the concrete realization of other types, so that we can do the test first, which type of test on the first realization of any type, and Regardless of whether or not to contact the class has been achieved.
Virtual object (mock object) is born for this need. Through The reflex mechanism, dynamically at runtime to create a virtual object. In the test code, we can verify these virtual object has been correctly deployed, can also clear cases, to return the value of a particular scenario. Once the target of these virtual services provided by the test-class virtual object can be linked as the other with a substitute for the real objects, thus easy to build a perfect test environment.
JMock is to help create a mock object tool, which is based on Java development, testing and development in the Java environment has unparalleled advantages, but more importantly, it greatly simplifies the use of virtual objects.
In this paper, through a simple test case to illustrate how JMock help us achieve this isolation test. There are three major categories, User, UserDAO, and UserService. In this paper, we only test UserService, ready virtual UserDAO. For the User, as a result of their own is just too simple a POJO, can not test. However, if you are a perfectionist, but also can use the virtual JMock it. In this field, JMock almost omnipotent. :)
User is a POJO, which in the view data and mapping . Its code is as follows:
package com.sarkuya.model;
public class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
} UserDAO responsible for dealing with the database through the database to preserve, access to User information. Although we do not know how JMock reflection JDK mechanism to achieve the isolation test, but at least should know, JDK reflection mechanism in the run-time required to create a dynamic interface type must be defined. JMock in the use of the environment, because we have to virtual UserDAO, means that the interface must be defined UserDAO. Code is as follows:
package com.sarkuya.dao;
import com.sarkuya.model.User;
public interface UserDAO {
public void saveUser(User user);
public User getUser(Long id);
} UserService there UserDAO reference, through its external services to provide application-level. Accordingly, we first define the interface (although in this article, as a category being tested, UserService do not have to interface, but if after such needs to be virtual, but also with the interface should be, For this reason, we have defined its the interface).
package com.sarkuya.service;
import com.sarkuya.dao.UserDAO;
import com.sarkuya.model.User;
public interface UserService {
public void setUserDAO(UserDAO userDAO);
public void saveUser(User user);
public User getUser(Long id);
} Can see that, in addition to setUserDAO (), its the other way as UserDAO. This is a design pattern in a typical application window mode, the application only through the provision of services UserService, and UserService internal UserDAO to achieve by calling the corresponding function.
According to the principle of the test first, you should write the test first, and then prepared to achieve. Here to prepare the realization of the main reasons is to make readers more clearly what we then want to test. This article is highlighted as a result of the use of JMock, coupled with relatively simple UserServiceImpl, it first set out its code is as follows:
package com.sarkuya.service.impl;
import com.sarkuya.dao.UserDAO;
import com.sarkuya.model.User;
import com.sarkuya.service.UserService;
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
public UserServiceImpl() {
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public User getUser(Long id) {
return userDAO.getUser(id);
}
public void saveUser(User user) {
userDAO.saveUser(user);
}
} The following is a testing UserService code:
package com.sarkuya.service;
import com.sarkuya.dao.UserDAO;
import com.sarkuya.model.User;
import com.sarkuya.service.impl.UserServiceImpl;
import junit..*;
import org.jmock.Mock;
import org.jmock.MockObjectTestCase;
public class UserServiceTest extends MockObjectTestCase {
private UserService userService = new UserServiceImpl();
private Mock userDAO = null;
public UserServiceTest(String testName) {
super(testName);
}
protected void setUp() throws Exception {
userDAO = new Mock(UserDAO.class);
userService.setUserDAO((UserDAO)userDAO.proxy());
}
protected void tearDown() throws Exception {
}
public static Test suite() {
TestSuite suite = new TestSuite(UserServiceTest.class);
return suite;
}
public void testGetUser() {
User fakeUser = new User("John");
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(fakeUser));
User user = userService.getUser(1L);
assertNotNull(user);
assertEquals("John", user.getName());
}
public void testSaveUser() {
User fakeUser = new User("John");
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(fakeUser));
User user = userService.getUser(1L);
assertEquals("John", user.getName());
userDAO.expects(once()).method("saveUser").with(same(fakeUser));
user.setName("Mike");
userService.saveUser(user);
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(user));
User modifiedUser = userService.getUser(1L);
assertEquals("Mike", user.getName());
}
} This code should be noted that there are a few points:
1, the test category of JMock inherited MockObjectTestCase
2, private Mock userDAO = null; note userDao is a virtual object to prepare
3, in the setup () will userDAO.class imported Mock () and then through the proxy () method returns an instance of a class UserDAO agents (ie, virtual object instance), and assignment in userService
4, in testGetUser () method, if we are the first line of first and second lines of code masked, we can see, this is a real test environment code. First obtain a User, and then confirm their non-null value, and then confirmed his name as "John". At this point, in a real environment, the success of the code to test the premise UserDAO must be connected to a database, and then return after a User to UserService.
But the problem is that so far, not to mention UserDAO not connect to database through a series of complicated and painful process, and we have not yet been realized even UserDAO interface! So why add the first line and second lines of code can do after? This is where the power of JMock. First example of a test used fakeUser, and then through a series of instructions, in the second line of code should be JMock told how to "false." Although this code is very long, we can make the following understanding:
1) userDAO.expects (once ()): We look forward to userDAO the implementation of a method is the first time, if this method is not implemented, or implemented over the second test would not have passed
2) method ( "getUser"): the expectations of the method was once known as userDAO.getUser ()
3) with (eq (1L)): the implementation of getUser () method, confirmed the introduction of the parameter values for the "1L"
4) will (returnValue (fakeUser)): the above conditions are met, returns a false object, that is before us examples of fakeUser
Generally speaking, when setting up the second line after the statement, JMock on the monitor in the background, and to ensure that userDAO.getUser () must be, and only once, and the parameters "1L" has the right to pass on this method, once these conditions were met, on the return fakeUser.
In the third line, User user = userService.getUser (1L) will trigger all of these conditions, as an incentive, it accepted the prize and fakeUser assignment in user object. And the fourth line the following five elements and are targets of this user testing, do not pass strange.
5) testSaveUser () method similar to the principle. The idea is that the id of "1" Remove the user from the database, changed the name to "Mike", and then kept to a database, and then removed from the database the user, to ensure that their name has been changed.
The fifth line of userDAO.expects (once ()). Method ( "saveUser"). With (same (fakeUser)) is rather special. First of all, with (same (fakeUser)) shows that the introduction of this parameter must be fakeUser example, even if we adopted the following statement user.setName ( "Mike"), but only changed its name attribute, and examples of fakeUser quote did not change, so can meet the conditions. Secondly, not later. Will (returnValue (fakeUser)), because userDAO.saveUser () do not need to return any objects or basic data types.
In addition, when once again the implementation of userDAO.expects () when, JMock will monitor the conditions of its reset. We can also userDAO.reset () to explicitly monitor the condition is clear.
Through the above-mentioned examples of code and its description, we see that the use of JMock the key is to first set up to monitor the conditions of the test to write the corresponding statement. Once set up better monitoring of conditions, at a certain block of code is finished, if the monitoring conditions have not been met, or did not pass the expects () again to reset the conditions, or through the reset () to remove explicit condition monitoring, testing will be can not.
Introduced over the basic use of JMock. A basic usage, accounting for a comprehensive master JMock knowledge required for learning more than 70%. For more details on the JMock, interested readers can visit the Web site to learn JMock.







