Sunday 14 April 2019

java - How do I test a private function or a class that has private methods, fields or inner classes?




How do I unit test (using xUnit) a class that has internal private methods, fields or nested classes? Or a function that is made private by having internal linkage (static in C/C++) or is in a private (anonymous) namespace?



It seems bad to change the access modifier for a method or function just to be able to run a test.


Answer




Update:



Some 10 years later perhaps the best way to test a private method, or any inaccessible member, is via @Jailbreak from the Manifold framework.




@Jailbreak Foo foo = new Foo();
// Direct, *type-safe* access to *all* foo's members
foo.privateMethod(x, y, z);
foo.privateField = value;


This way your code remains type-safe and readable. No design compromises, no overexposing methods and fields for the sake of tests.




If you have somewhat of a legacy Java application, and you're not allowed to change the visibility of your methods, the best way to test private methods is to use reflection.




Internally we're using helpers to get/set private and private static variables as well as invoke private and private static methods. The following patterns will let you do pretty much anything related to the private methods and fields. Of course, you can't change private static final variables through reflection.



Method method = TargetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);


And for fields:




Field field = TargetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);






Notes:
1. TargetClass.getDeclaredMethod(methodName, argClasses) lets you look into private methods. The same thing applies for
getDeclaredField.
2. The setAccessible(true) is required to play around with privates.




No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...