mardi 6 octobre 2015

JMockit: mocking ResultSet.next() to return multiple values from more than one method

I have following code with a public method - method1 - that is calling 2 private methods from the method under test. Both of these methods have DB interactions and some more processing like assignment of class variables based on some logic. I need to write jUnits for this method1.

Problem:

rs.next();returns(true, false, true, false);

When mocking rs.next() - I am able to get true, false as 2 responses from this method when it's called from method2 but when making same call from method3, I am getting a 'false' value the first time (third time in total since 2 calls were already made from method2) this method is called - instead of getting true, as I have set in Expecations block.

My expectation is since I have mentioned 4 values in Expectations block for the mocked object of ResultSet and for the call rs.next(); any 4 calls throughout the course of current test should return the values in the braces in the given order.

A colleague mentioned it might be that mocking is somehow not working on the ResultSet object (or getting reset) by the time of the call from method3, and the rs.next() call is defaulting to false, not able to find the return value for the call. If this is the case, I would be very interested to find if there is a lifetime of the 4 return values I have set in the Expectations block and what is resetting the ResultSet object?

I have the following 2 limitations:

  1. I cannot modify the code under test to accomodate my junits. So please don't answer/comment with how I should fix the design. I know its bad design but have to write the junits as is.
  2. I cannot mock either of the 2 private methods being called from method1, as both are setting private variables of the class and I need the values to be set.

Code being tested:

Class ClassA{
public void method1(){
//some code
String tempString1 = method2();
String tempString2 = method3();
}

private String method2() throws Exception{
Connection con;
CallableStatement cs;
ResultSet rs = null;
try{//Code obtaining connection, executing procedure
rs = cs.executeQuery();}
//catch block with Exception handling
finally{
try{
if(rs!=null){rs.close();}
if(cs!=null){cs.close();}
if(con!=null){con.close();}
}//catch block with exception handling
}
try{
if(rs.next()){
//do something OPERATION1
}
}//catch block with exception handling.
//finally block with closing each of cs, con and rs.
}//End of Method2

private void method3() throws Exception{
Connection con;
CallableStatement cs;
ResultSet rs = null;
try{//Code obtaining connection, executing procedure
rs = cs.executeQuery();}
//catch block with Exception handling
finally{
try{
if(rs!=null){rs.close();}
if(cs!=null){cs.close();}
if(con!=null){con.close();}
}//catch block with exception handling
}
try{
if(rs.next()){
//do something OPERATION2
}
}//catch block with exception handling.
//finally block with closing each of cs, con and rs.
}//end of method3
}//end of ClassA

jUnit:

@Test
public void method1Test(@Mocked final Connection con, @Mocked final CallableStatement cs, @Mocked final ResultSet rs) throws Exception{
final ClassA classA = new classA();
new Expectations(classA){{
//some code
rs.next(); returns(true, false, true, false);
//more code    
}};
classA.method1();
new Verifications(){{//some code}};
}

1 commentaire: