JMockit is a java framework for mocking objects in JUnit testing. It uses the instrumentation apis that modify the bytecode during run time to dynamically create classes. The API model can be seen here.
The following are short descriptions about the most used tools offered by JMockit:
The following are short descriptions about the most used tools offered by JMockit:
- JMockit Expectations: This class is the most used for a mocking the results of a method by specifying what is expected when a particular method is invoked. JMockit names the setting of expectations as record phase and when the actual call to the method happens, its called the replay phase. Thus the jargon record-replay model. The object/class whose method is going to be mocked should be annotated using the @Mocked annotation in the class scope or should be declared locally in the expectations block.
The following example will make all the mumbo jumbo above clear.
/************* "Person.java" *********/ public class Person { String name = "Abhi" ; public String getName() { return name; } public void setName(String name) { this.name = name; } } /************* "Department.java" *********/ public class Department{ Person person = new Person();//Person is the 'collaborator'- a fancy name for third party object public String getPersonName(){ return person.getName(); } } /************* "DepartmentTest.java" *********/ public class DepartmentTest{ @Mocked Person person;//The mocked object.Note that I am NOT using new to create an instance. @Test public void testGetName(){ Department dept = new Department(); new Expectations(){ //locally defined objects are automatically considered mocked { person.getName();//Setting the expected behaviour here. returns("Nandan");//Will return Nandan instead of Abhi } }; String name = dept.getPersonName(); assertEquals("Name Should be Nandan","Nandan",name); } }
The code is pretty self explanatory, I am mocking the getName() method to return "Nandan" which may take up various forms when you are writing the unit tests.
Before we jump onto Verifications, Expectations block is a strict checking mechanism-the test run will fail if - The calls in the expectation block are not replayed.
- There is more than one call of the same method
- There is a call for another method
- JMockit Verifications: As the name suggests this class is used to *verify* something after a test method call has taken place. Extending the record-replay model, it becomes record-replay-verify model. Verifications can be used to explicitly check if a call has been made and how many times.Now onto the code....
/************* "Person.java" *********/ public class Person { String name = "Abhi" ; public String getName() { return name; } public void setName(String name) { this.name = name; } } /************* "Department.java" *********/ public class Department{ Person person = new Person();//Person is the 'collaborator'- a fancy name for third party object public String getPersonName(){ return person.getName(); } } /************* "DepartmentTest.java" *********/ public class DepartmentTest{ @Mocked Person person;//The mocked object.Note that I am NOT using new to create an instance. @Test public void testGetNameCalls(){ Department dept = new Department(); String name = dept.getPersonName(); new Verifications(){ { person.getName();//verify that this method is called when dept.getPersonName() is invoked } }; } }
We can also specify the constraints for the number of times a method has to be called. Go through this link to understand how times,minTimes, and maxTimes fields can be used. - JMockit Inline MockUps : This is my personal favourite. And I would say its the most powerful feature of JMockit to redefine methods/static blocks/constructors. I will be posting how to do all of that in the coming blogs. As of now, we'll see how to create a inline mockup that redefines a method for our test case.See the JMockit documention of MockUp for more information.
/************* "Person.java" *********/ public class Person { String name = "Abhi" ; public String getName() { return name; } public void setName(String name) { this.name = name; } } /************* "Department.java" *********/ public class Department{ Person person = new Person();//Person is the 'collaborator'- a fancy name for third party object public String getPersonName(){ return person.getName(); } } /************* "DepartmentTest.java" *********/ public class DepartmentTest { @Test public void testGetNameCalls(){ Department dept = new Department(); new MockUp
(){ @Mock //A directive to JMockit to redefine the method. Remember!! public String getPersonName(){ return null; } }; String name = dept.getPersonName();//this call returns a null because of redefinition assertNull(name); } }
great post...much more comprehensive then the official tutorial
ReplyDeleteThanks Lucian!
DeleteVery nicely written, helped me a lot
ReplyDeleteThank you gaurav...
DeleteVery helpful..Thanks Abhi..
ReplyDeleteThanks Subramanya! You made my day :)
DeleteYour tutorials are very helpful.. Thanks abhi :)
ReplyDeletenice post sir..keep it up :)
ReplyDeleteNice post, it really helpful to understand Jmockit.
ReplyDeleteGood stuff Abhi!
ReplyDeleteCouple links you provided are giving 404...sure, difficult to update old links...:)
new MockUp…
ReplyDeleteDo we suppose to make the Department as department when Mocking or it is just a typo?
Thanks for the tutorial though.
believe its a typo...
Deletehttp://jmockit.org/api1x/mockit/MockUp.html
Hi Abhi,
ReplyDeleteMyself Sundar, firstof all your blog is very useful to me. I have some clarifications as below as,
Now, I have a one simple program as xml reading, I need to integrate JMockit to that, Could you please give some idea
Thank you for the such good examples :-)
ReplyDelete