0

I have a tree data structure for example

public class Tree {
    class Node {
        //stuffs...
    }

    private Node root;

    // ...
}

I'm using junit4. In my unit test, I'd like to run some sanity check where I need to traverse the tree (e.g. check the binary search tree properties are preserved). But since the root is kept private, I can't traverse it outside the class.

Something I can think about are:

  1. A getter for root can prevent the reference itself from being changed, but external code still may change fields in root.
  2. A test is not a part of the data structure itself, I don't really want to put it in the Tree class. And even I do, I have to delete them after the test is done.

Please tell me the right thing to do, thanks.

SedriX
  • 500
  • 3
  • 10
  • Some unit test frameworks can access a private field or method. The other way to do this is to provide a package-private method that returns the root or does the test for you. – markspace Apr 04 '19 at 18:03
  • Possible duplicate: [How do I test a private function or a class that has private methods, fields or inner classes?](https://stackoverflow.com/questions/34571/how-do-i-test-a-private-function-or-a-class-that-has-private-methods-fields-or). – SedriX Apr 05 '19 at 00:36

1 Answers1

2

There's multiple things you can do, a few options are:

  1. Make a public getter (but this breaks code encapsulation, only should be considered if you for some odd reason cannot put tests in the same package)

  2. Write a package-private getter and place the tests in the same package (probably the best solution)

  3. Use reflection to gain access to the value (not recommended)

I would personally go with option 2 (please see my last paragraph for my recommend answer, since I would not do any of the above). This is what we used in industry to test things that we can't normally access to. It is minimally invasive, it doesn't break encapsulation like a public getter does, and it doesn't require you to do intrusive reflection code.

As a discussion on why we didn't use (3), I was on a project once where the lead developer decided to do exactly this in all his unit tests. There were tens of thousands of unit tests which were all using reflection to verify things. The performance gain we got from converting them away from a reflection-assisting library was nice enough that we got a lot more snappy feedback when we ran our unit tests.

Further, you should ask yourself if you need to do such tests. While testing is nice, you should ideally be unit testing the interface of your stuff, not reaching into the guts to assert everything works. This will make it very painful if you ever need to refactor your class because you'll invalidate a bunch of tests when you touch anything. Therefore I recommend only testing the public methods and be very rigorous in your tests.

Water
  • 3,245
  • 3
  • 28
  • 58