Java tool for testing private methods?

心不动则不痛 提交于 2019-12-04 04:15:57

it would be nice to be able to call private methods in the test code like

@MakeVisibleForTesting Something something = new Something();
Assert.assertEquals(43, something.internalSecret());

There's such thing as a method annotation, check out dp4j's @TestPrivates:

@Test
@TestPrivates 
//since the method is annotated with JUnit's @Test this annotation is redundant. 
// You just need to have dp4j on the classpath.
    public void somethingTest(){
      Something something = new Something();
      int sthSecret = something.internalSecret();
       Assert.assertEquals(43, sthSecret); //cannot use something.internalSecret() directly because of bug [dp4j-13][2] 
    }

It seems like a lot of trouble to do this implementation. It may not be worth it. Rather just make the method package default.

However, if you are determined to call private method, you can use setAccessible in yourDecapsulated_something class to allow call via reflection. So it's fairly simple.

I'll answer the "In general" question :-) It only takes a few lines of code to make a method accessible via reflection and there are quite a number of libraries, utils, APIs etc that provide methods for doing so. There's also probably many different techniques you could use in your own code. For example bytecode manipulation, reflection, class extensions, etc. But I'd be inclined to keep things simple. Whilst it can be useful to test private methods, it's also likely that you will only want to test a few. So engineering something complex is probably overkill. I'd just use an established API, or write a quick method to access the private methods I was interested in and let it be done at that.

There are number of approaches to take

  • Don't test private methods as they are hidden implementation details which should never make a difference to the caller.
  • Make the methods package local so a caller cannot access them, but you can access them in the same package i.e. a unit test.
  • Make the unit test an inner class or provide a package local inner class. Not sure this is an improvement!
  • Use reflection to access the methods of the class. This is like marking a method rpivate when its not and is a confusion IMHO. You should be only marking a method private when it is truely private.

I worked on a project a few years back that generated classes to make it easier to unit test private methods. http://java.net/projects/privateer/

It generated extra classes that made it easier than calling reflection, e.g. if you had MyClass.myPrivateMethod() it would generate a _MyClass class that would allow invocation of myPrivateMethod directly.

It was never really finished and was kind of useful for a few cases, but overall I wouldn't recommend testing private methods unless absolutely necessary. Usually redesigning them into utility classes (with package access if you're worried about users using them) is a better option.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!