How to write unit tests for method which calls other methods? - java

This is a really bad sample of code. Sorry about that.
I want to write a unit test for myMethod(). This only calls other methods and return String str1. I don't see there is any need of testing this code.
public class MyClass{
private String str1;
private String str2;
private void m1(){..}
private String m2(){
// do something
return someString;
}
public String myMethod(String s1){
str2 = s1;
m1();
str1 = m2();
return str1;
}
}

There are various ways to write unit tests.
A) You observe behavior. You create an object of your class under test, then you call methods; and then you assertThat on the values that are returned.
B) When your object uses other objects, then you might have to turn to mocking frameworks, for example to verify that you see the expected method calls on those objects.
In your case, it really depends on what m1/m2 are doing. As said - the best unit tests are those that only check the "observable" behavior of your code under test. Like those examples:
#Test(expected=NullPointerException.class)
public void testMyMethodWithNull() {
new MyClass().myMethod(null);
}
The above would check that when calling your method with null ... a NPE is thrown.
#Test
public void testMyMethodWithEmptyString() {
MyClass underTest = new MyClass();
assertThat(underTest.myMethod(""), is("some expected string for empty input"));
}
That one does some different checking for EMPTY input.
And so you work your way through all inputs that make sense. Of course, the idea here is that all possible behavior of your class under test can be checked this way. If there are others that come into play, you have to take them into consideration of course. But ideally, that should not be the case: you should design all your code so that it can be fully tested as easily as possible; and ideally without the need to write anything else but such kind of tests.

I completely agree with GhostCat:
[…] the best unit tests are those that only check the "observable" behavior of your code under test.
Therefore, only test the public contract of your class under test (CUT).
However, there're rare situations in which you may need to test private methods, e.g. if you're working with legacy code. One way to do this is with PowerMockito:
PowerMockito.verifyPrivate(cut).invoke("m1");
Where cut is an instance of your CUT – MyClass.
Checkout these questions for further opinions and references:
Should I test private methods or only public ones?
How do I test a class that has private methods, fields or inner classes?
Making a private method public to unit test it...good idea?

"I don't see there is any need of testing this [private method]."
Yes. That's right.
A method that is private doesn't need any direct testing. Of course, private methods should be covered, but since they are private and NOT a part of your exposed API, they don't need to be tested as directly as public methods.
This book--JUnit in Action: Second Edition--outlines many strategies for using JUnit effectively. Implementing TDD is one way to make sure that your class's non-public functionality is well-covered by your tests. That is, you write your unit tests first, then you implement your class to pass those tests. In this way, you only write functionality that you need, as defined by your tests.

Related

JUnit test methods can't return a value

Why JUnit test methods can't return a value?
Documentation says (emphasis mine):
Test methods and lifecycle methods may be declared locally within the current test class, inherited from superclasses, or inherited from interfaces (see Test Interfaces and Default Methods). In addition, test methods and lifecycle methods must not be abstract and must not return a value.
Why is it enforced like this?
Is this purely a design choice? Is it a best practice?
One thing I haven't yet seen mentioned is that one of the reasons behind this design decision is historical.
Before test cases where marked by annotations, they were analysed by JUnit via reflection - all public void methods, the name of which started with test, and that didn't have any arguments, were considered test cases that were run by the framework.
Had these methods allowed to also return a value, you could not have created a public helper method starting with test that calculated a value commonly used in some tests, or the framework runner would have tried to run it.
You should have made them private anyway I guess.
Additionally, this was also the high time of "a method name that starts with a verb should do something" (rather than calculate something).
What is the reasoning behind this?
Think of each test method as being the logical analog of a public static void main(String[]) method in a classic Java application. There needs to be a well known method signature so that the JUnit framework is able to identify the test methods, and call them in a standard way.
As to the specific design points you are querying:
The reason that the methods cannot be abstract is that they need to be callable. You can't call an abstract method.
The reason that methods cannot return values is that the test framework would not be able to do anything useful with a returned value. (It would not be impossible to discard any result, but what is the point of a testcase result that can't be used?)
I was thinking maybe we could reuse one test method within another.
If you wanted to reuse code in unit tests, you would just use ordinary methods and other OO features of Java; e.g. base classes, helper classes, etcetera. There are few situations where you would want a free-standing test method and a "component" (for want of a better word) of another test method. And if you did you could write something like this.
public void test_xxx() {
real_test_xxx();
}
public int real_test_xxx() {
...
}
public void test_yyy() {
...
res = real_test_xxx()
...
}
Is this purely a design choice? Is it a best practice?
There are no best practices!
These are design choices that are guided by the general requirements and practicalities of unit testing1. Particularly, the requirement that unit test authors should NOT need to build configurations to tell the test framework what to do.
Note that TestNG takes a similar approach. If a TestNG #Test method is declared as returning a value, it is not treated as a test method; see Can a test method return a value in TestNG
Either way, unless you are proposing to implement yet another Java test framework, this is all moot.
1 - If there were strong practical reasons for needing abstract test methods or test methods that returned values, someone would have done something about it. The masses (of unit test writers) would rise up and overthrow the tyranical regime (of test framework developers). (Reprise of the "We won't be fooled again" by The Who.)
Is this purely a design choice?
Yes. In theory, nothing prevents the Junit runner (component thats runs tests of a test class) from accepting as valid a test method with a return value.
Is it a best practice?
Indeed. More you restrict the ways of specifying a unit test method, more you ensure that no misuse happens.
For example look at that simple example that would suppose a test method to return a value.
A addFoo() test method that asserts that the method does what it is expected and that also returns the Foo fixture created :
#Test
public Foo addFoo(){
Foo foo = new Foo(...);
// call the api ...
sut.addFoo(foo);
// assertion
assertEquals(...);
// return the foo fixture
return foo;
}
And here a addFooBar() test method that retrieves the Foo fixture created by the previous method and then asserts that the method addFooBar() does what it is expected :
#Test
public void addFooBar(){
Foo foo = addFoo();
Bar bar = new Bar(..., foo);
// call the api ...
sut.addFooBar(bar);
// assertion
assertEquals(...);
}
That lays multiple issues :
Does the method addFoo() should be executed multiple times ? It may hurt the test speed execution and make test reports unclear.
The addFoo() test result may make the addFooBar() test result to fail in spit of a correct implementation.
How to diagnostic the issue origin ? We added useless complexity.
The addFoo() test result may make the addFooBar() test result to succeed in spit of a incorrect implementation. Indeed, an incorrect implementation in addFoo() may compensate an incorrect implementation in addFooBar()
Test methods should be executed independently
If the tests can not run independently then they are not unit tests.
A unit test should not rely on any external state
If test method will return a value, it may applies that test results should be used/relevant to other tests
Same best practice in TestNG
Since TestNG follows best practices for unit testing, which means a unit test method should not have a return value
you can write some private methods and reuse them like
#Test
public void test1() {
privateTest();
}
#Test
public void test2() {
privateTest();
// more Logic
}
private int privateTest() {
return 0;
}

How do I replace my instances with Easymock

I am trying to unit test a class using EasyMock. To simplify things, I have made an example below. What I want is for the StringBuilder instance to be replaced by the EasyMock instance during testing. (As it is not the functionality of the StringBuilder I want to be tested.) Unfortunately this does not work in the example below. In other tests I have a workaround by setting the instance variables with an EasyMock instance, but with this example I am unable to do this, because it is a locally instantiated object I care about.
Who can help me out?
The class to be tested:
package example.easymock
public class Example {
public String exampleMethod() {
StringBuilder string = new StringBuilder();
string.append("hello");
return string.toString();
}
}
The testing class:
package example.easymock
import needed classes
public class ExampleTest {
#Test
public void exampleMethodTest() {
StringBuilder stringMock = EasyMock.createMock();
Example example = new Example();
stringMock.append("hello");
EasyMock.expect(stringMock.toString()).andReturn("hi");
EasyMock.replay(stringMock);
example.exampleMethod();
}
}
Using just EasyMock it's going to be impossible. PowerMock does contain power to do that however:
expectNew(StringBuilder.class).andReturn(stringMock);
You need to set up PowerMock configuration correctly for that to work of course - see more here
That doesn't change the fact, that exactly this impossibility is what (in part) lead to widely adopting Inversion of Control as a design principle. Also, as a rule, any method you can not test is a method that could be refactored to be better (and testable). PowerMock should only be used for tests when code itself can't be changed to be better.
That is of course assuming that StringBuilder is just an example and not literally what you're trying to do. If it is - don't bother, you can assume that any methods that are part of language libraries work as advertised.

How to test a method that depends on another already tested method?

I'm working on a method that can be considered a specialization of another already defined and tested method. Here's an example code to illustrate:
public class ProductService {
public void addProduct(Product product) {
//do something
}
public void addSpecialProduct(Product product) {
addProduct(product);
//do something after
}
}
I don't want to copy the tests I have for addProduct which are already pretty complex. What I want is when I define the tests for addSpecialProduct, I just make sure that it also calls addProduct in the process. If this were a matter of 2 classes collaborating, it's easy to have the collaborator mocked and just verify that the target method gets called (and stub it if necessary). However, the 2 methods belong to the same class.
What I'm thinking right now is to spy on the object I'm testing, something like:
public void testAddSpecialProduct() {
//set up code
ProductService service = spy(new DefaultProductService());
service.addSpecialProduct(specialProduct);
verify(service).addProduct(specialProduct);
//more tests
}
However, I'm wondering whether this approach somehow defeats the purpose of unit testing. What's the general consensus on this matter?
I think it depends on how rigorous you want to be with your unit testing. In the extreme sense, unit testing should only test the behavior, not the implementation. This would mean you would need to duplicate your tests (or take take #chrylis' suggestion of abstracting out common functionality to helpers). Ensuring the other method is called is testing the implementation.
However in reality, I think your idea of spying on the instance to ensure the other well-tested method is called is a good idea. Here are my reasons:
1) It simplifies your code.
2) It becomes immediately clear to me what is happening. It says to me that everything that has been tested for the other method will now also be true, and here are the extra assertions.
One day you may modify the implementation so that the other method is not called, and this will cause your unit tests to fail, which is what people are generally trying to avoid by not testing the implementation. But in my experience, changes like this are much more common when the behavior is going to change anyway.
You may consider refactoring your code. Use the strategy pattern to to actually implement the functionality for adding products and special products.
public class ProductService {
#Resource
private AddProductStrategy normalAddProductStrategy;
#Resource
private AddProductStrategy addSpecialProductStrategy;
public void addProduct(Product product) {
normalAddProductStrategy.addProduct(product);
}
public void addSpecialProduct(Product product) {
addSpecialProductStrategy.addProduct(product);
}
}
There will be 2 Implementations of the AddProductStrategy. One does that what happend in your original ProductService.addProduct implementation. The second implementation will delegate to the first one and then do the additional work required. Therefore you can test each strategy separately. The second strategy implementation is then just a decorator for the first implementation.

How to test and mock 2 private methods in the same class in Java? [duplicate]

How do I use JUnit to test a class that has internal private methods, fields or nested classes?
It seems bad to change the access modifier for a method just to be able to run a test.
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:
TargetClass.getDeclaredMethod(methodName, argClasses) lets you look into private methods. The same thing applies for
getDeclaredField.
The setAccessible(true) is required to play around with privates.
The best way to test a private method is via another public method. If this cannot be done, then one of the following conditions is true:
The private method is dead code
There is a design smell near the class that you are testing
The method that you are trying to test should not be private
When I have private methods in a class that are sufficiently complicated that I feel the need to test the private methods directly, that is a code smell: my class is too complicated.
My usual approach to addressing such issues is to tease out a new class that contains the interesting bits. Often, this method and the fields it interacts with, and maybe another method or two can be extracted in to a new class.
The new class exposes these methods as 'public', so they're accessible for unit testing. The new and old classes are now both simpler than the original class, which is great for me (I need to keep things simple, or I get lost!).
Note that I'm not suggesting that people create classes without using their brain! The point here is to use the forces of unit testing to help you find good new classes.
I have used reflection to do this for Java in the past, and in my opinion it was a big mistake.
Strictly speaking, you should not be writing unit tests that directly test private methods. What you should be testing is the public contract that the class has with other objects; you should never directly test an object's internals. If another developer wants to make a small internal change to the class, which doesn't affect the classes public contract, he/she then has to modify your reflection based test to ensure that it works. If you do this repeatedly throughout a project, unit tests then stop being a useful measurement of code health, and start to become a hindrance to development, and an annoyance to the development team.
What I recommend doing instead is using a code coverage tool, such as Cobertura, to ensure that the unit tests you write provide decent coverage of the code in private methods. That way, you indirectly test what the private methods are doing, and maintain a higher level of agility.
From this article: Testing Private Methods with JUnit and SuiteRunner (Bill Venners), you basically have 4 options:
Don't test private methods.
Give the methods package access.
Use a nested test class.
Use reflection.
Generally a unit test is intended to exercise the public interface of a class or unit. Therefore, private methods are implementation detail that you would not expect to test explicitly.
Just two examples of where I would want to test a private method:
Decryption routines - I would not
want to make them visible to anyone to see just for
the sake of testing, else anyone can
use them to decrypt. But they are
intrinsic to the code, complicated,
and need to always work (the obvious exception is reflection which can be used to view even private methods in most cases, when SecurityManager is not configured to prevent this).
Creating an SDK for community
consumption. Here public takes on a
wholly different meaning, since this
is code that the whole world may see
(not just internal to my application). I put
code into private methods if I don't
want the SDK users to see it - I
don't see this as code smell, merely
as how SDK programming works. But of
course I still need to test my
private methods, and they are where
the functionality of my SDK actually
lives.
I understand the idea of only testing the "contract". But I don't see one can advocate actually not testing code—your mileage may vary.
So my trade-off involves complicating the JUnit tests with reflection, rather than compromising my security and SDK.
The private methods are called by a public method, so the inputs to your public methods should also test private methods that are called by those public methods. When a public method fails, then that could be a failure in the private method.
In the Spring Framework you can test private methods using this method:
ReflectionTestUtils.invokeMethod()
For example:
ReflectionTestUtils.invokeMethod(TestClazz, "createTest", "input data");
Another approach I have used is to change a private method to package private or protected then complement it with the #VisibleForTesting annotation of the Google Guava library.
This will tell anybody using this method to take caution and not access it directly even in a package. Also a test class need not be in same package physically, but in the same package under the test folder.
For example, if a method to be tested is in src/main/java/mypackage/MyClass.java then your test call should be placed in src/test/java/mypackage/MyClassTest.java. That way, you got access to the test method in your test class.
To test legacy code with large and quirky classes, it is often very helpful to be able to test the one private (or public) method I'm writing right now.
I use the junitx.util.PrivateAccessor-package for Java. It has lots of helpful one-liners for accessing private methods and private fields.
import junitx.util.PrivateAccessor;
PrivateAccessor.setField(myObjectReference, "myCrucialButHardToReachPrivateField", myNewValue);
PrivateAccessor.invoke(myObjectReference, "privateMethodName", java.lang.Class[] parameterTypes, java.lang.Object[] args);
Having tried Cem Catikkas' solution using reflection for Java, I'd have to say his was a more elegant solution than I have described here. However, if you're looking for an alternative to using reflection, and have access to the source you're testing, this will still be an option.
There is possible merit in testing private methods of a class, particularly with test-driven development, where you would like to design small tests before you write any code.
Creating a test with access to private members and methods can test areas of code which are difficult to target specifically with access only to public methods. If a public method has several steps involved, it can consist of several private methods, which can then be tested individually.
Advantages:
Can test to a finer granularity
Disadvantages:
Test code must reside in the same
file as source code, which can be
more difficult to maintain
Similarly with .class output files, they must remain within the same package as declared in source code
However, if continuous testing requires this method, it may be a signal that the private methods should be extracted, which could be tested in the traditional, public way.
Here is a convoluted example of how this would work:
// Import statements and package declarations
public class ClassToTest
{
private int decrement(int toDecrement) {
toDecrement--;
return toDecrement;
}
// Constructor and the rest of the class
public static class StaticInnerTest extends TestCase
{
public StaticInnerTest(){
super();
}
public void testDecrement(){
int number = 10;
ClassToTest toTest= new ClassToTest();
int decremented = toTest.decrement(number);
assertEquals(9, decremented);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(StaticInnerTest.class);
}
}
}
The inner class would be compiled to ClassToTest$StaticInnerTest.
See also: Java Tip 106: Static inner classes for fun and profit
As others have said... don't test private methods directly. Here are a few thoughts:
Keep all methods small and focused (easy to test, easy to find what is wrong)
Use code coverage tools. I like Cobertura (oh happy day, it looks like a new version is out!)
Run the code coverage on the unit tests. If you see that methods are not fully tested add to the tests to get the coverage up. Aim for 100% code coverage, but realize that you probably won't get it.
If using Spring, ReflectionTestUtils provides some handy tools that help out here with minimal effort. For example, to set up a mock on a private member without being forced to add an undesirable public setter:
ReflectionTestUtils.setField(theClass, "theUnsettableField", theMockObject);
Private methods are consumed by public ones. Otherwise, they're dead code. That's why you test the public method, asserting the expected results of the public method and thereby, the private methods it consumes.
Testing private methods should be tested by debugging before running your unit tests on public methods.
They may also be debugged using test-driven development, debugging your unit tests until all your assertions are met.
I personally believe it is better to create classes using TDD; creating the public method stubs, then generating unit tests with all the assertions defined in advance, so the expected outcome of the method is determined before you code it. This way, you don't go down the wrong path of making the unit test assertions fit the results. Your class is then robust and meets requirements when all your unit tests pass.
If you're trying to test existing code that you're reluctant or unable to change, reflection is a good choice.
If the class's design is still flexible, and you've got a complicated private method that you'd like to test separately, I suggest you pull it out into a separate class and test that class separately. This doesn't have to change the public interface of the original class; it can internally create an instance of the helper class and call the helper method.
If you want to test difficult error conditions coming from the helper method, you can go a step further. Extract an interface from the helper class, add a public getter and setter to the original class to inject the helper class (used through its interface), and then inject a mock version of the helper class into the original class to test how the original class responds to exceptions from the helper. This approach is also helpful if you want to test the original class without also testing the helper class.
Testing private methods breaks the encapsulation of your class because every time you change the internal implementation you break client code (in this case, the tests).
So don't test private methods.
The answer from JUnit.org FAQ page:
But if you must...
If you are using JDK 1.3 or higher, you can use reflection to subvert
the access control mechanism with the aid of the PrivilegedAccessor.
For details on how to use it, read this article.
If you are using JDK 1.6 or higher and you annotate your tests with
#Test, you can use Dp4j to inject reflection in your test methods. For
details on how to use it, see this test script.
P.S. I'm the main contributor to Dp4j. Ask me if you need help. :)
If you want to test private methods of a legacy application where you can't change the code, one option for Java is jMockit, which will allow you to create mocks to an object even when they're private to the class.
PowerMockito is made for this.
Use a Maven dependency:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
Then you can do
import org.powermock.reflect.Whitebox;
...
MyClass sut = new MyClass();
SomeType rval = Whitebox.invokeMethod(sut, "myPrivateMethod", params, moreParams);
I tend not to test private methods. There lies madness. Personally, I believe you should only test your publicly exposed interfaces (and that includes protected and internal methods).
If you're using JUnit, have a look at junit-addons. It has the ability to ignore the Java security model and access private methods and attributes.
Here is my generic function to test private fields:
protected <F> F getPrivateField(String fieldName, Object obj)
throws NoSuchFieldException, IllegalAccessException {
Field field =
obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (F)field.get(obj);
}
Please see below for an example;
The following import statement should be added:
import org.powermock.reflect.Whitebox;
Now you can directly pass the object which has the private method, method name to be called, and additional parameters as below.
Whitebox.invokeMethod(obj, "privateMethod", "param1");
I would suggest you refactoring your code a little bit. When you have to start thinking about using reflection or other kind of stuff, for just testing your code, something is going wrong with your code.
You mentioned different types of problems. Let's start with private fields. In case of private fields I would have added a new constructor and injected fields into that. Instead of this:
public class ClassToTest {
private final String first = "first";
private final List<String> second = new ArrayList<>();
...
}
I'd have used this:
public class ClassToTest {
private final String first;
private final List<String> second;
public ClassToTest() {
this("first", new ArrayList<>());
}
public ClassToTest(final String first, final List<String> second) {
this.first = first;
this.second = second;
}
...
}
This won't be a problem even with some legacy code. Old code will be using an empty constructor, and if you ask me, refactored code will look cleaner, and you'll be able to inject necessary values in test without reflection.
Now about private methods. In my personal experience when you have to stub a private method for testing, then that method has nothing to do in that class. A common pattern, in that case, would be to wrap it within an interface, like Callable and then you pass in that interface also in the constructor (with that multiple constructor trick):
public ClassToTest() {
this(...);
}
public ClassToTest(final Callable<T> privateMethodLogic) {
this.privateMethodLogic = privateMethodLogic;
}
Mostly all that I wrote looks like it's a dependency injection pattern. In my personal experience it's really useful while testing, and I think that this kind of code is cleaner and will be easier to maintain. I'd say the same about nested classes. If a nested class contains heavy logic it would be better if you'd moved it as a package private class and have injected it into a class needing it.
There are also several other design patterns which I have used while refactoring and maintaining legacy code, but it all depends on cases of your code to test. Using reflection mostly is not a problem, but when you have an enterprise application which is heavily tested and tests are run before every deployment everything gets really slow (it's just annoying and I don't like that kind of stuff).
There is also setter injection, but I wouldn't recommended using it. I'd better stick with a constructor and initialize everything when it's really necessary, leaving the possibility for injecting necessary dependencies.
A private method is only to be accessed within the same class. So there is no way to test a “private” method of a target class from any test class. A way out is that you can perform unit testing manually or can change your method from “private” to “protected”.
And then a protected method can only be accessed within the same package where the class is defined. So, testing a protected method of a target class means we need to define your test class in the same package as the target class.
If all the above does not suits your requirement, use the reflection way to access the private method.
As many above have suggested, a good way is to test them via your public interfaces.
If you do this, it's a good idea to use a code coverage tool (like EMMA) to see if your private methods are in fact being executed from your tests.
Today, I pushed a Java library to help testing private methods and fields. It has been designed with Android in mind, but it can really be used for any Java project.
If you got some code with private methods or fields or constructors, you can use BoundBox. It does exactly what you are looking for.
Here below is an example of a test that accesses two private fields of an Android activity to test it:
#UiThreadTest
public void testCompute() {
// Given
boundBoxOfMainActivity = new BoundBoxOfMainActivity(getActivity());
// When
boundBoxOfMainActivity.boundBox_getButtonMain().performClick();
// Then
assertEquals("42", boundBoxOfMainActivity.boundBox_getTextViewMain().getText());
}
BoundBox makes it easy to test private/protected fields, methods and constructors. You can even access stuff that is hidden by inheritance. Indeed, BoundBox breaks encapsulation. It will give you access to all that through reflection, but everything is checked at compile time.
It is ideal for testing some legacy code. Use it carefully. ;)
First, I'll throw this question out: Why do your private members need isolated testing? Are they that complex, providing such complicated behaviors as to require testing apart from the public surface? It's unit testing, not 'line-of-code' testing. Don't sweat the small stuff.
If they are that big, big enough that these private members are each a 'unit' large in complexity—consider refactoring such private members out of this class.
If refactoring is inappropriate or infeasible, can you use the strategy pattern to replace access to these private member functions / member classes when under unit test? Under unit test, the strategy would provide added validation, but in release builds it would be simple passthrough.
I want to share a rule I have about testing which particularly is related to this topic:
I think that you should never adapt production code in order to
indulge easer writing of tests.
There are a few suggestions in other posts saying you should adapt the original class in order to test a private method - please red this warning first.
If we change the accessibility of a method/field to package private or protected, just in order to have it accessible to tests, then we defeat the purpose of existence of private access directive.
Why should we have private fields/methods/classes at all when we want to have test-driven development? Should we declare everything as package private, or even public then, so we can test without any effort?—I don't think so.
From another point of view: Tests should not burden performance and execution of the production application.
If we change production code just for the sake of easier testing, that may burden performance and the execution of the application in some way.
If someone starts to change private access to package private, then a developer may eventually come up to other "ingenious ideas" about adding even more code to the original class. This would make additional noise to readability and can burden the performance of the application.
With changing of a private access to some less restrictive, we are opening the possibility to a developer for misusing the new situation in the future development of the application. Instead of enforcing him/her to develop in the proper way, we are tempting him/her with new possibilities and giving him ability to make wrong choices in the future.
Of course there might be a few exceptions to this rule, but with clear understanding, what is the rule and what is the exception? We need to be absolutely sure we know why that kind of exception is introduced.

Junit test for private method

I read this question: How do I test a class that has private methods, fields or inner classes? and it seems that I might have a code smell, but my code is very simple to actually refactor. what is wrong in the design that I have created.
I have created a delegate class for processing some actions it has three methods execute(Action); PopulateActionHandlers() and executeActionhandlers();
My class is like below:
public class DelegateHandler{
Map<Integer,ActionHandlers> handlerMaps;
public execute(Action action){
populateActionHandlers(action);
executeActionHandlers();
}//end of execute
//This method can create and populate more than one handlers in handlerMap
private populateActionHandlers(action){
handlerMap = new LinkedHashMap<ActionHandlers>();
if (action.isMultimode()){
handlerMap.add(1,new handler(action.getabc()));
handlerMap.add(2,new handler(action.getabc()-1));
}else{
handlerMap.add(1,new handler(action));
}
}//end of populateActionHandlers
//This method can execute more than one handlers in handlerMap
private executeActionHandlers(){
for(ActionHandler actionHandler : handlerMap.values){
actionHandler.executeAction();
}
}//end of executeActionHandlers
}
Now I want to test populateActionHandlers() method with JUnit, which I made private as there is no need to expose it outside this class. If I test the execute() method then it will test both populateActionHandlers() and executeActionHandlers() methods which is testing two units at the same time, I want to test them separately. The design (I think) seems alright to me and doesnt allow any issues but then I would either change the access to the method (and only for the sake of testing it doesn't justify that in my opinion, right?) or to use reflection (is that a good idea, it does not feel right somehow, do people usually use reflection for junit testing?). So the only thing that cant be ruled out is code smell. But may be my code sinus is not really helping me So I would like to understand if I can improve this code.
The recommendation not to test private methods should not prevent one to do a weird design by leaving out private method, but should enforce to test only methods that have clear semantics.
Private methods are usually technical helpers. Their semantics can change if the underlying data structures change, they can even be optimized away if the calling public methods use another algorithm to achieve the same goals.
I would rewrite the programm in following way:
...
public execute(Action action){
Map<Integer,ActionHandlers> handlerMap = populateActionHandlers(action);
executeActionHandlers(handlerMap);
}
...
Storing results of one function into a private field only to retrieve it from this field in another function is not threadsafe and harder to maintain.
Yet this refactoring would break all (yet not writte) tests that did test the private method of your example, because the interface is changed. If you had only tested the public method, the all tests would be valid after this refactoring.
I know few cases where testing private methods is ok. While testing private methods is often avoidable, I think the checking of private state is sometimes a better alternative than only checking the public state of objects. Such checks may be not as robust (reasons as above) but the public state is often incomplete and hard to assert. In both cases I use the framework picklock which enables one to access private methods and fields in a convenient way.

Categories