Saturday, September 10, 2016

Mocking Static Methods using JMockit

What is mocking and when do we need it?
Mocking is redirecting your method call to your own defined call which will output some sample output which is defined by you. 

We use mocking mostly for Database method calls and RMI method calls, because we don't want server calls happening for unit testing our code, so instead we say to the code when you need to hit so and so methods in a class, here is what you should return, so that call will not hit the actual code but the mocked output which we provided will be returned back. 


We need the below jars for our sample tutorial:
jmockit-1.27.jar
hamcrest-core-1.3.jar and 
junit4-4.8.2.jar

Sample Code:

We can mock the static method in two ways one way is by using MockUp and other way is to use Expectations, i written code for both, but MockUp is throwing some warning so i continued using Expectations, Will explain the below logic. 

We have a static method named getDBObject(String inTable,int col) which accepts two parameters say table name and column name and say it has logic inside it which will hit the database and returns the value present in that column. As we might be using this in multiple places we don't want to hit the database for unit testing so we are mocking this method call in my UnitTesting class UtJMockTestCases. 

Let's inspect test1() method:

new Expectations(DBUtils.class) {{
DBUtils.getDBObject("one",1); result = "XYZ";
DBUtils.getDBObject("two",2); result = "ABC";
}};
assertEquals(DBUtils.getDBObject("one",1),"XYZ");
assertEquals(DBUtils.getDBObject("two",2),"ABC");
assertEquals(DBUtils.getDBObject("two",3),"Null");

these are the expectations for the BDUtils class, so we have written two expectations as of now, but if we are calling only of the method calls with the same parameters then we will get an exception saying missing one more method call, so if you need some method call to mock then only add it to expectation, rule is what ever method calls you are mocking in the expectations you should use all of them in the testingMethod here it is test1(). 

Let's inspect test2() method:
new Expectations(DBUtils.class) {{
DBUtils.getDBObject("three",anyInt); result = "ABC";
}};
assertEquals(DBUtils.getDBObject("three",1),"ABC");

so now the interesting part is the above mocking of the methods with parameters is strict checking, so when you say "one",1 it expects String to be one and integer to be 1, if you pass other say ("one",2) then you will receive Null as return because call will be gone to original method and not mocked method, so now there is a requirement like i will pass "three" as a string but i can pass any number as integer parameter so then also my mocked method should only get executed and not the original one, so in such conditions there are any* parameters in Expectations class, link, you can use it like for int it is anyInt, boolean it is anyBoolean as such and for any kind of Objects it is just any.
import static org.junit.Assert.*;

import org.junit.BeforeClass;
import org.junit.Test;
import mockit.Expectations;
import mockit.Mock;
import mockit.MockUp;

class DBUtils{
public static String getDBObject(String inTable,int col){
return "Null";
}
}

public class JMockTestCases {
@BeforeClass
public static void setUp(){
/*new MockUp<DBUtils>(){    
  // Redefine the method here,But With No static modifier
  @Mock
  public String getDBObject(){
   return "PERSON";
  }  
   };*/
}
@Test
public void test1() throws Exception{
new Expectations(DBUtils.class) {{
DBUtils.getDBObject("one",1); result = "XYZ";
DBUtils.getDBObject("two",2); result = "ABC";
}};
assertEquals(DBUtils.getDBObject("one",1),"XYZ");
assertEquals(DBUtils.getDBObject("two",2),"ABC");
assertEquals(DBUtils.getDBObject("two",3),"Null");
}
@Test
public void test2() throws Exception{
new Expectations(DBUtils.class) {{
DBUtils.getDBObject("three",anyInt); result = "ABC";
}};
assertEquals(DBUtils.getDBObject("three",1),"ABC");
}
}




1 comment:

  1. Samanya gyan ke liye aap iss website se zarur padhe. http://www.kidsfront.com/competitive-exams.html

    ReplyDelete