Do not violate my privacy

Good day! The article will be about one completely insignificant point in coding.

For example, many of my colleagues said - Doch, das ist ganz normal! "And, what, all the rules, I found something to complain about!" But nonetheless.





There are a few things about coding that piss me off. Well, actually not a few. :), the older I get, the more and more such things, the character does not improve. But in the top - when developers write tests for private methods. Oh no! When for this they remove the word private from the method and the method becomes package-private.





Here, you review a class like this, lines like 3K, written in the best traditions of procedural programming, and there are 10 public methods, 10 private, and 15 more package-private. And we haven't heard about interfaces - this is a service, let's just inject it like that! Ok, you think, now we'll roll up our sleeves, we'll move all public methods into the interface, helper-s, them into a separate package - in short, we'll cut this madness into pieces according to SRP. But then you find out that package-private methods have been jerking from other places for a long time. So we have all the classes in one package dumped! If something can be misused, it will be misused for sure, as they say.





Yes, everyone knows, you don't need to write tests for private methods, if you do this, then something is wrong with the design, and so on. But, damn it, people do it anyway, and I must say, not without reason. Imagine the above class had zero test coverage at all. And you need to refactor. This is how package-private methods come in. But how can we be - they cut Whitebox out of Mockito, of course it remained in PowerMock , but for the sake of this, dragging PowerMock into the project, and the syntax is no better than a direct call through reflection. You can, of course, write your own bike, but ... And so it doesn't work out like that.





But imagine that we have an interface for accessing private elements of a class - methods, fields. What the hell, you say, the guy is working hard. But like this:





There is a class:





public class ObjectWithPrivates {
    private final AtomicInteger count = new AtomicInteger(0);
    private String name;

    private String methodToTest(String in) {
        return name + in + count.incrementAndGet();
    }
}
      
      



Test:





interface TestPrivates {
    void setName(String name);
    String methodToTest(String in);
    AtomicInteger getCount();
}

@Test
void testPrivates() {
    ObjectWithPrivates obj = new ObjectWithPrivates();
    TestPrivates objWithPrivates = API.lookupPrivatesIn(obj)
                                      .usingInterface(TestPrivates.class);

    objWithPrivates.setName("Andromeda");
    String in = objWithPrivates.methodToTest("in");
    AtomicInteger count = objWithPrivates.getCount();

    Assertions.assertEquals("Andromedain1", in);
    Assertions.assertEquals(1, count.get());
}
      
      



As you can see, using the interface, we can fetch private methods, and access private fields. Well, you can tell right away from the code what is happening. Keep in mind that all manipulations occur with obj and you can, for example, set all private fields of obj and then pull the public method.





You can access the private fields / methods of the parent class:





TestPrivates accessToPrivates = API.lookupPrivatesIn(obj)
                                   .lookupInSuperclass()
                                   .usingInterface(TestPrivates.class);
      
      



Or you can pull static methods:





TestPrivates accessToPrivates = lookupPrivatesIn(SomePOJOClass.class)
                                .usingInterface(TestPrivates.class);
accessToPrivate.someStaticPrivateMethod();
      
      



Or you can create an object using a private constructor.





Under the hood, there is standard reflection and Dynamic Proxy, no additional dependencies.





Here is a link to the testprivates project . Use for tests only.





All with the coming, do not get sick!








All Articles