Friday, October 12, 2007

accessing private fields

Today I learned again something new from the java reflection API. You can set private fields in a class. This comes in handy when you want to write a Unit test for a class that depends om some external services or classes;

Lets say we have:


public class ClassUnderTest {

private OtherClass otherClass;

public doSomethingWithOtherClass() {

otherClass.someFunction()
}
}


When we want to test this class we might want to Mock the OtherClass because we are not interested in the functionality of the otherClass. Our testcase has no direct access to the otherClass field so we need to use some magic to do so.

public class MyTestCase {
@Test
public void testDoSomethingWithOtherClass {
Field otherClassField = ClassUnderTest.class.getDeclaredField("otherClass"); (1)
otherClassField.setAccessible(true); (2)

ClassUnderTest classUnderTest = new ClassUnderTest();
OtherClass otherClass = createMock(OtherClass.class);
otherClass.someFunction();
otherClassField.set(classUnderTest,otherClass); (3)
replay(otherClass)
classUnderTest.doSomethingWithOtherClass();
verify(otherClass);

}
}


(1) We use the reflection api to fetch the private Field of the ClassUnderTest
(2) We make it accessible
(3) We set the value on a instance of ClassUnderTest

And we're set.

createMock() replay() and verify() are functions from EasyMock which is a verify nice framework for creating Mock objects. You should certainly take a look at it if you don't know it yet. @Test is a annotation from testng unit test framework.



No comments: