简体   繁体   中英

Is it good to use reflection API on access of private method and variable?

I want to access a private method of class while writing Junit test cases.Is it good to use reflection API? Somewhere I found that the reflection API is slow.P

Please give a suggestion.

Yes, the approach is totally fine and, I guess, not uncommon for most projects that do thorough unit testing. The reflection API was probably created for exactly this purpose.

Why do you worry about the reflection API being slow? It only slows down your tests, it doesn't matter for the users at normal runtime. However, if your tests become too slow because of reflection API access, then just upgrade your development hardware. I don't think it can ever be a problem, even when you hit really large number of module tests in the millions.

Just don't change your actual non-testing program source code, like changing everything to public because you want to test it. This would actually be a very bad thing to do. You want a clean API and clean classes, so you don't want to expose everything.

Testing can, and usually does, have implications on your software architecture like encouraging a more loosely coupled architecture and therefore the use of architecture patterns like dependency injection. However, testing must not define your API. The API should just be what you think it ought to be, not what the unit tests need (which would probably be setting everything to public, which is obviously not what language designers intended, when they introduced modifiers like private or protected).

In later testing phases, however, like system testing, it is obviously no longer necessary to use reflection API, since you're just triggering the normal, public API of your code and observe/check the response. You usually don't want to go down into the code and check additional things in this testing phase. However, there might be certain circumstances, like checking for flags or very critical values that you want to double-check.

You should think about your design. If you have to think about testing private methods your class probably do more that it should and violates SRP in some point. I'm strongly recommending you to create new classes with smaller responsibilities. It does not look like your class is well defined, so cutting it should be fine.

You can test your private methods using reflection but still - it is not good way for that.

It is a bad practice according to normal programming flow on java and on junit test especially, you need to verify system under test (your class) as same way you will be use it in your app. Reflection breaking class incapsulation.

If you want to test private methods of something you need to completely rearrange your development workflow and use test driven development. Example how to test private methods properly in tdd way. Assume we have class A and test for it:

class A {

    public int calculate() {
        //very complex code
        // 50+ lines of code
    }

}

class ATest {

    public void shouldCalculateComplexThing() {
        A a = new A();
        int answer = a.calculate();
        Assert.assertEquals(answer, 42);

    }

}

after that we mention that calculate() method is too big to understand in first look and we need to refactor it:

class A {

    public int calculate() {
        return calculateFirstPart() + calculateSecondPart();
    }

    private int calculateFirstPart() {
        //code
    }
    private int calculateSecondPart() {
        //code
    }

}

Because we have test to it we already have the same answer 42 , but we changed code and introduce private methods and we don't need to test it because they tested through method calculate() . It is a right way to testing private fields, methods, and other class realization details in tdd

Ideally, you should not need to access any hidden variable in your unit test. But if you have to, then one possibility is to use package-protected visibility (no modifier). That way, your unit test can read / write the field, as long as it resides in the same package as the class under test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM