1

As i understand it, the correct way to test private methods is via reflection? So if we test a method via reflection, we need to make an instance of the class, get the method, invoke it and so on. However, what do we do if the class that we create uses data from other objects that will return null / be null without the correct previously made objects.

Thanks

Biscuit128
  • 5,218
  • 22
  • 89
  • 149
  • See also [What's the proper way to test a class with private methods using JUnit?](http://stackoverflow.com/questions/34571/whats-the-proper-way-to-test-a-class-with-private-methods-using-junit) – avandeursen Mar 05 '12 at 09:49

3 Answers3

4

I personally think you should avoid writing tests on private methods. Using reflection to me is a design smell - you should ideally write tests only against the exposed public interface of your class.

If you feel the need to test a private method, then this suggests to me that you should do one of the following:

  • Recognise that the method really should be part of the public interface and make it public
  • Write a test against some existing public methods of the class that indirectly test the private method
  • Write a new public method that exposes the behaviour you wish to test
  • Refactor the behaviour out into another class which you can test (thanks Tom for the extra idea!)
mikera
  • 105,238
  • 25
  • 256
  • 415
  • 1
    Or even move the behaviour out to a new class (without changing the interface of the existing class), and test that. – Tom Anderson Mar 04 '12 at 12:19
  • but should everything not be encapsulated down to the level where the least amount of functionality is exposed? I was of the understanding that whatever can be private should be private - and that therfore will be where most of the complex functionality will be – Biscuit128 Mar 04 '12 at 12:32
  • @Ricki - encapsulation is all well and good but if you've got that much complexity in a class it's possible you are violating the Single Responsibility Principle. Perhaps your class should actually be a composite of several other classes (each of which could implement different key functionality and have a testable public interface)? – mikera Mar 04 '12 at 13:10
3

As i understand it, the correct way to test private methods is via reflection?

It's the only way (if you're only testing the private method, and not some other public method that calls the private method), as you cannot access the private methods from outside of the class (except with reflection). I don't usually write separate tests for private-methods, but it can be useful.

what do we do if the class that we create uses data from other objects that will return null / be null without the correct previously made objects.

In unit-tests, you "mock" the outside dependencies, either using a mocking-library, such as Mockito or some other, or write anonymous or separate mocking classes implementing the interface of the dependency. The idea is that you define some exact behavior for the outside dependencies, so their behavior won't affect the testing of the actual class. If the fields holding the references are private, you need to use reflection to inject the objects into them.

In integration-testing, you use the actual implementations of the outside dependencies.

Community
  • 1
  • 1
esaj
  • 15,875
  • 5
  • 38
  • 52
  • 2
    Most of the time you should avoid testing private methods, as you want to test your classes behavior (public API), not how it's internals work. – vertti Mar 04 '12 at 12:01
  • This is a widespread misconception, and if you followed it to the letter, you would never unit test and you would only do functional testing. The rule of thumb is "If it can break, you should test it". You can also consider making the private method package protected, so you don't have to use reflection to test it. – Cedric Beust Mar 04 '12 at 19:52
1

You can use an existing instance of the class (say, the instance on which you've already tested the public methods).

Now just invoke the private method (found through reflection) of that instance, which, presumably, must have all the 'previously made' objects.

sinharaj
  • 1,093
  • 2
  • 11
  • 16