使用反射为私有方法编写测试

时间:2019-07-02 06:07:48

标签: android testing tdd android-testing

我有一个NetworkManager班。我确实有很多private方法需要为它们编写测试。

起初,我没有找到任何针对我的私有方法编写测试的解决方案。无论如何,我找到了一种方法来访问我的私有方法并为它们编写一些测试。

我使用了反射来访问我的函数并为其编写测试。有一个简单的私有方法的示例:

 private String myFun (String input){
        return input+"hello";
    }

有一个测试类,我在其中使用了反射:

@RunWith(AndroidJUnit4.class)
public class NetworkManagerTest {

    private static NetworkManager networkManager;
    private Context appContext = InstrumentationRegistry.getTargetContext();

    private @ADType
    int adType = ADType.TYPE_BANNER;


    @BeforeClass
    public static void setup() {

        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {

                networkManager = NetworkManager.getInstance();
                networkManager.addNetworkCall(TestUtil.getSampleSystemRequest());

            }
        });
    }

    @Test
    public void sample() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        Method method = NetworkManager.class.getDeclaredMethod("myFun", String.class);
        method.setAccessible(true);
        String output = (String) method.invoke(networkManager, "Ehsan");

        Assert.assertEquals("Ehsanhello", output);
    }

}

这很好。但是问题是,用反射方式为私有方法编写测试可以通过多少种方式进行?

有没有更好的方法来实现这一目标?

2 个答案:

答案 0 :(得分:2)

  

但是问题是,通过反射使用私有方法编写测试可以通过这种方式进行多少次?

     

有没有更好的方法来实现这一目标?

最常见的方法是放弃该目标。

从历史上看,TDD的重点一直在验证行为,而不是实现细节。部分原因在于,测试使我们可以放心地自由更改代码的内部设计,因为这些测试将使我们警觉到行为的任何意外更改。

因此,如果我们需要进行测试以确保某些私有方法中的逻辑正确,则可以找到依赖于该逻辑的公共API的用例,并编写可测量公共API行为的测试。

我们可以通过将临时故障注入私有方法中并验证测试可以检测到故障来校准测试。

这样做,我们可以选择通过内联私有方法来重构代码;在这种情况下,所有测试仍然应该通过,因为我们还没有更改测试对象的行为-我们只是移动了细节。

如果您要积极改善应用程序的内部设计,那么您需要与该内部设计脱钩的测试。

答案 1 :(得分:1)

我很热衷于说,如果您要测试的私人方法太多,则意味着您的班级承担了太多的责任。私有方法可以按逻辑分组并提取到其他类中。

这就是为什么我不接受番石榴的@VisibleForTesting注解的原因。