mockito-all-1.9.5.jar | |
File Size: | 1581 kb |
File Type: | jar |
Hello buddy, you are here, it means either you are looking to make your unit test cases more effective or you are told to use Mockito or you have been told to mock certain objects in your Junit. So reasons can be many, but purpose is same – you want to know about Mockito.
So friend, lets start but first thing first – have you analysed various other aspects before coming to the decision to Mock the objects. First check some below definitions & decide if you really need to mock(taken from http://www.vogella.com/tutorials/Mockito/article.html + some other additions) -
A dummy object is passed around but never used, i.e., its methods are never called. Such an object can for example be used to fill the parameter list of a method. So here you don’t need to mock anything just create blank object & pass it along till you are sure that this object will not be used along your test flow.
Fake objects have working implementations, but are usually simplified, for example they use an in memory database and not a real database. Here you can create a dummy class having all the public methods from the actual class & just return the required values from those methods without having any business implementation & I don’t think that you even need to worry about the database, if that database is not your part of logic. Such fake objects can be considered over Mocking the objects when you need to use every method of that object, so why to mock every method call rather just have a fake object & use it.
A stub class is an partial implementation for an interface or class with the purpose of using an instance of this stub class during testing. Stubs usually do responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls. This part I didn’t understand properly as I think that this I can achieve using the fake object like above.
A mock object is a dummy implementation for an interface or a class in which you define the output of certain method calls. Now this is the purpose or topic for us in the following examples.
I will not be taking the configuration steps & binding with Spring or other kind of frameworks, request you to go for google for this. I will be taking the implementation part of Mockito in your Junit & its different features to help you to use Mockito quickly as it took me some time to understand various caveats, but will be happy if you can come out of those issues quickly after this.
Lets hit the Mockito road. First very basics. I will be taking everything as example or scenario as I like this way. Attached is the mockito jar I have used.
Example 1 : ‘Employee.java’ is my class which I want to test & use mockito for this as my class is using the objects of ‘Address.java’, which is not mine & I need to mock such objects. I have one Person.java interface implemented by Employee.java. Currently Address.java is not to be tested as it is interface & will be mocked for our Junit.
package address;
public interface Address {
public void setCity(String city);
public String getCity();
public void setState(String state);
public String getState();
public void setCountry(String country);
public String getCountry();
}
package person;
import address.Address;
public interface Person {
public void setName(String name);
public String getName();
public void setAddress(Address address);
public Address getAddress();
}
Below is the Employee.class implementing the above interface.
package person;
import java.util.logging.Logger;
import address.Address;
public class Employee implements Person {
private Logger LOGGER = Logger.getLogger("LOGGER");
private String name;
private Address address;
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void setAddress(Address address) {
this.address = address;
LOGGER.info("Address is set " + address.getCity());
}
@Override
public Address getAddress() {
LOGGER.info("Got the address " + address.getState());
return address;
}
}
You can check that Address.java is an interface & my class needs object of the concrete class to run & to test. But at least I can test it by mocking the object for Address like shown below. Also please check the comments mentioned along.
package person;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import address.Address;
//@FixMethodOrder(MethodSorters.NAME_ASCENDING)
// Above annotation is used to make the test cases to execute in the ascending
// of their names. MethodSorters provide 3 types to sort the methods but it is
// never suggested to write test cases to make them to execute in particular order.
// Test cases must be independent of each other. But in case if have such requirement
// then one can use the above annotation but for this Junit4.6 or above is required.
// You need to use below annotation if want to execute the test cases using mocked object
// & it is one of the way to use the mocked objects.
@RunWith(MockitoJUnitRunner.class)
public class EmployeeTest {
// Using below annotation we can mock the object of a class or interface.
// Below I have used the interface.
@Mock
Address address;
Person employee;
// Below annotation is used to execute the method before the execution of
// every test case. @BeforeClass is also provided to execute the method once when
// the class is loaded.
// So depending on the requirement use the annotations.
@Before
public void setup(){
// Below is another way to mock the required object. mock() is overloaded
// to provide different features, check it once. Though it will not impact if use
// both @Mock & below way to mock the the objects but why use both ways
// to do the same thing. address = Mockito.mock(Address.class);
employee = new Employee();
// Mocking the method calls of the mocked object.
Mockito.when(address.getCity()).thenReturn("Pune");
Mockito.when(address.getState()).thenReturn("MH");
Mockito.when(address.getCountry()).thenReturn("India");
employee.setAddress(address);
}
// Below is the test case annotated using @Test
// @Test further provides 2 properties which can be used if required - expected & timeout
@Test
public void SetAddress() {
// if the setup() needs to be executed before the execution of every test case then better
// to use the annotation @Before. If only once then can execute the below statement.
// setup();
System.out.println(address.getCountry());
employee.setAddress(address);
}
@Test
public void testGetAddress() {
// If the setup method is not executed here before the get call on employee object then
// will get the NullPointerException because employee object will not get initialized.
// Even if we put the employee object initialization outside the setup() then still we will
// get the NullPointerException, but this time it will be for the get() call on Address
// as address object will not be there for employee object due to employee object will be
// fresh for this test case though it seems that employee object got the address object
// in previous test case.
// setup();
if(employee == null || employee.getAddress() == null){
System.out.println("Employee is null");
}else{
System.out.println(employee.getAddress().getCity());
}
}
}
I hope that it will help to kick start the mocking. Will make the things more complex on page 'Part 2'.
So friend, lets start but first thing first – have you analysed various other aspects before coming to the decision to Mock the objects. First check some below definitions & decide if you really need to mock(taken from http://www.vogella.com/tutorials/Mockito/article.html + some other additions) -
A dummy object is passed around but never used, i.e., its methods are never called. Such an object can for example be used to fill the parameter list of a method. So here you don’t need to mock anything just create blank object & pass it along till you are sure that this object will not be used along your test flow.
Fake objects have working implementations, but are usually simplified, for example they use an in memory database and not a real database. Here you can create a dummy class having all the public methods from the actual class & just return the required values from those methods without having any business implementation & I don’t think that you even need to worry about the database, if that database is not your part of logic. Such fake objects can be considered over Mocking the objects when you need to use every method of that object, so why to mock every method call rather just have a fake object & use it.
A stub class is an partial implementation for an interface or class with the purpose of using an instance of this stub class during testing. Stubs usually do responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls. This part I didn’t understand properly as I think that this I can achieve using the fake object like above.
A mock object is a dummy implementation for an interface or a class in which you define the output of certain method calls. Now this is the purpose or topic for us in the following examples.
I will not be taking the configuration steps & binding with Spring or other kind of frameworks, request you to go for google for this. I will be taking the implementation part of Mockito in your Junit & its different features to help you to use Mockito quickly as it took me some time to understand various caveats, but will be happy if you can come out of those issues quickly after this.
Lets hit the Mockito road. First very basics. I will be taking everything as example or scenario as I like this way. Attached is the mockito jar I have used.
Example 1 : ‘Employee.java’ is my class which I want to test & use mockito for this as my class is using the objects of ‘Address.java’, which is not mine & I need to mock such objects. I have one Person.java interface implemented by Employee.java. Currently Address.java is not to be tested as it is interface & will be mocked for our Junit.
package address;
public interface Address {
public void setCity(String city);
public String getCity();
public void setState(String state);
public String getState();
public void setCountry(String country);
public String getCountry();
}
package person;
import address.Address;
public interface Person {
public void setName(String name);
public String getName();
public void setAddress(Address address);
public Address getAddress();
}
Below is the Employee.class implementing the above interface.
package person;
import java.util.logging.Logger;
import address.Address;
public class Employee implements Person {
private Logger LOGGER = Logger.getLogger("LOGGER");
private String name;
private Address address;
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void setAddress(Address address) {
this.address = address;
LOGGER.info("Address is set " + address.getCity());
}
@Override
public Address getAddress() {
LOGGER.info("Got the address " + address.getState());
return address;
}
}
You can check that Address.java is an interface & my class needs object of the concrete class to run & to test. But at least I can test it by mocking the object for Address like shown below. Also please check the comments mentioned along.
package person;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import address.Address;
//@FixMethodOrder(MethodSorters.NAME_ASCENDING)
// Above annotation is used to make the test cases to execute in the ascending
// of their names. MethodSorters provide 3 types to sort the methods but it is
// never suggested to write test cases to make them to execute in particular order.
// Test cases must be independent of each other. But in case if have such requirement
// then one can use the above annotation but for this Junit4.6 or above is required.
// You need to use below annotation if want to execute the test cases using mocked object
// & it is one of the way to use the mocked objects.
@RunWith(MockitoJUnitRunner.class)
public class EmployeeTest {
// Using below annotation we can mock the object of a class or interface.
// Below I have used the interface.
@Mock
Address address;
Person employee;
// Below annotation is used to execute the method before the execution of
// every test case. @BeforeClass is also provided to execute the method once when
// the class is loaded.
// So depending on the requirement use the annotations.
@Before
public void setup(){
// Below is another way to mock the required object. mock() is overloaded
// to provide different features, check it once. Though it will not impact if use
// both @Mock & below way to mock the the objects but why use both ways
// to do the same thing. address = Mockito.mock(Address.class);
employee = new Employee();
// Mocking the method calls of the mocked object.
Mockito.when(address.getCity()).thenReturn("Pune");
Mockito.when(address.getState()).thenReturn("MH");
Mockito.when(address.getCountry()).thenReturn("India");
employee.setAddress(address);
}
// Below is the test case annotated using @Test
// @Test further provides 2 properties which can be used if required - expected & timeout
@Test
public void SetAddress() {
// if the setup() needs to be executed before the execution of every test case then better
// to use the annotation @Before. If only once then can execute the below statement.
// setup();
System.out.println(address.getCountry());
employee.setAddress(address);
}
@Test
public void testGetAddress() {
// If the setup method is not executed here before the get call on employee object then
// will get the NullPointerException because employee object will not get initialized.
// Even if we put the employee object initialization outside the setup() then still we will
// get the NullPointerException, but this time it will be for the get() call on Address
// as address object will not be there for employee object due to employee object will be
// fresh for this test case though it seems that employee object got the address object
// in previous test case.
// setup();
if(employee == null || employee.getAddress() == null){
System.out.println("Employee is null");
}else{
System.out.println(employee.getAddress().getCity());
}
}
}
I hope that it will help to kick start the mocking. Will make the things more complex on page 'Part 2'.