Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing private variables - always bad practice?

To give some background I've been learning java for about 10 months now so I am really not that experienced. I have been reading a bit recently on how how its bad practice to test private methods and variables.

In the perfect world you shouldn't do this as it suggests bad design - however, I am working with a legacy framework where most methods are called via reflection and it IS bad design, but I cannot change that no matter what. Please don't reply saying "you should redesign your code" as I cannot change the way the framework works.

I want to test that a 'flow' class behaves in a certain way and calls the right methods depending on the state of private variables, and I want to make sure that certain methods set private instance variables to a correct value if another private variable has a certain value. This is so when I make future changes to the class I can ensure that the flow/behavior of the class hasn't broken or changed.

Now, because the flow is based largely on the state of private instance variables and because its bad to test the state of private instance variables - how else do I test the class?

Ways of testing the private variables that all work:

  1. Implement default access getters and setters at the end of the code and put the junit test class in same package. Comment these clearly that they should be used for testing only.

  2. Make instance variables default access instead of private and put junit test class in same package. No other classes in the same package will instantiate this class anyway.

  3. Test the private variables via reflection - I lose IDE functionality here as Eclipse won't refactor if I change the name of variables and could be a future pain of manually changing Strings to match variable names in the class to be tested.

Which of the three above is the "lesser" evil to use? Is it better to test private variables then have no tests at all?

like image 858
DeaIss Avatar asked Mar 29 '14 13:03

DeaIss


People also ask

Why is testing private methods bad?

In short, testing private functions (by using FRIEND_TEST or making them public or using reflection) that could otherwise be tested through a public interface can cause test duplication. You really don't want this, because nothing hurts more than your test suite slowing you down.

Is it good to test private methods?

The short answer is that you shouldn't test private methods directly, but only their effects on the public methods that call them. Unit tests are clients of the object under test, much like the other classes in the code that are dependent on the object.

Should I make a private method public for testing?

A unit test should test the public contract, the only way how a class could be used in other parts of the code. A private method is implementation details, you should not test it; as far as public API works correctly, the implementation doesn't matter and could be changed without changes in test cases.

Is it good to use ReflectionTestUtils?

Using reflection for unit testing is mostly fine. Of course, you should design your classes for testability, so that less reflection is required. Spring for example has ReflectionTestUtils . But its purpose is set mocks of dependencies, where spring was supposed to inject them.


1 Answers

The state of private fields is irrelevant to the correct functioning of the class. You shouldn't be testing private variables.

Test what the class does, not how it does it.

If you want to test that the class sets its internal state correctly, so it behaves in a particular way after that, then call the methods that set the state and test that the behaviour after that is correct.

It doesn't matter if it takes 1000's of tests to ensure that - they are only unit tests, so they'll be fast.

Future coders are at liberty to change the internal workings of a class, as long as the class' contract is upheld.

like image 189
Bohemian Avatar answered Sep 29 '22 13:09

Bohemian