0

Hi I am new to unit testing. Is it possible to access methods that are private?

A very simple example

ObjectA 
----------

File file;

private void setupFile (){
  //do something
  file = "C:\file.dat"
}

In TestCase

File sth = ObjectA.setupFile();
assertNotNull(sth);

I am unable to test whether the file variable is null in method ObjectA.setup() as I cannot run ObjectA.setupFile()

I am not sure about whether doing like this make sense in terms of unit testing.

So is that a better practice to write every method returning sth and set them public for easier unit testing?

Thanks in advance

Deco
  • 3,261
  • 17
  • 25
vincentlcy
  • 1,157
  • 2
  • 17
  • 19
  • Do not make private methods public for the sake of unit testing. Private methods will be called by public methods (if not, they should be removed). To keep track of private methods being called use a coverage tool. – Emond Nov 24 '11 at 07:00

2 Answers2

2

In general, you should avoid changing the access of a method/field to enable testing. If you do this then you risk developers using the method directly.

However, if you do need to, then making it protected as Deco says is a good way, so it's accessible from the JUnit tests. If you do this, make sure that it is well documented that this is an method for internal use.

A better way is to test the behaviour of the public methods; you shouldn't care about internal implementation details of a class, so you should only be testing public methods. It's hard to tell from your code, but presumably, the setupFile() has effects later on other methods, so you can test those effects, not the fact that file is not null.

External dependencies (such as dependencies on file system, environment variables) can be worked around in your tests, or injected directly into the class. For the general principle, see my answer to How to test code dependent on environment variables using JUnit?

Community
  • 1
  • 1
Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
  • Thanks for detailed answer. I do agree that we should not change the visibility in order to test. so unit testing is more like testing behavior of an object and the purpose I mentioned should be done by debugger + compiler – vincentlcy Nov 24 '11 at 12:16
0

If it is not absolutely necessary to have the method as private, you can have it as package private (i.e. default access) so that you can call it directly in a JUnit test.

Package private methods can only be used in the package that they are declared, and do not become part of the API of the class. You declare a method package private by putting no modifier on it's declaration.

Here's an example to demonstrate:

public class MyClass() {
 int foo;

 public MyClass() {
  this.foo = 0;
 }

 void notSoComplexCalculationMethod(int a) {
  foo = a * 2;
 }
  //Other methods here . . .
}

public class MyClassTest extends TestCase {
  private MyClass myClass;

  protected void setUp() {
    super.setUp();
    myClass = new MyClass();
  }

  public void testNotSoComplexCalculationMethod() {
   int a = 2;

   assertEquals(4, myClass.notSoComplexCalculationMethod(a));
   //Unit test passes, yay! Now you've tested a package private method.
   }
}
Deco
  • 3,261
  • 17
  • 25
  • Thanks for the answer as my application is small and wont be publish i think setting them package visibility will be helping a lot – vincentlcy Nov 24 '11 at 12:17