TDD测试时,需要访问Service层私有方法时,你应该这样办!

938 阅读2分钟

(私有方法?我偏要访问!)测试需要访问Service层私有方法时,你应该这样办!

前言

最近在写测试,TDD(测试驱动开发),然后写到了一个测试方法时,我还是照常调用了Service层,自己写的“public” 的 私有方法, (为什么这样说,因为这个方法只是为了提供了这个类的方法中某一个的方法使用,而创建的。没有任何复用可言,但是因为为了测试,所以写成了public,以便调用。) 我一直很诧异,为什么一直要这样搞,缺少了代码的完整真实可读性,可能会让读代码的人第一反应造成不必要的误解,然后我就开始了接下来的探究。

目标

把代码改成 private 关键字修饰,不加任何静态修饰符或者单例修饰等等。保证代码完整真实性。

代码

AccountServicelmpl内代码 不用在意方法内的内容

private String subCardBinLastChar(String cardNo) {
        if (cardNo.length() <= CARD_BIN_PREFIX_MIN_LENGTH) {
            throw new ServiceException(ResultCode.BANK_NON_SUPPORT);
        }
        if (cardNo.length() > CARD_BIN_PREFIX_MAX_LENGTH) {
            return StringUtils.substring(cardNo, 0, CARD_BIN_PREFIX_MAX_LENGTH);
        }
        return StringUtils.substring(cardNo, 0, cardNo.length() - 1);
    }

写了工具类用于调用这个一个参数的方法

/**
 * 用于测试返回Service静态方法
 * @author FYF
 * @date Created in 9:40 2020/6/22
 */
public class ExecutePrivateMethods {

    public static <T> Object ClassReflect(Class<T> TClass, String method) {
        Class cl = null;
        try {
            cl = TClass;
            Object Clazz = cl.newInstance();
            Method m1 = cl.getDeclaredMethod(method);

            m1.setAccessible(true);
            Object invoke = m1.invoke(Clazz);
            return invoke;
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

    }
    //带一个参数
    public static <T> Object ClassReflect(Class<T> TClass, String method,Object obj) {
        Class cl = null;
        try {
            cl = TClass;
            Object Clazz = cl.newInstance();
            Method m1 = cl.getDeclaredMethod(method,obj.getClass());

            m1.setAccessible(true);
            Object invoke = m1.invoke(Clazz,obj);
            return invoke;
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

    }
}

测试

    @ParameterizedTest
    @ValueSource(strings = {"12345678901234"})
    void testSubCardBinLengthForLong(String cardNo) {
        Object subCardBinLastChar = ExecutePrivateMethods.ClassReflect(AccountServiceImpl.class, "subCardBinLastChar", cardNo);
        String cardBin = subCardBinLastChar.toString();
        log.info("cardBin:{}", cardBin);
        assertEquals(AccountServiceImpl.CARD_BIN_PREFIX_MAX_LENGTH, cardBin.length());
    }

测试结果: 成功

在这里插入图片描述

关键代码


        Class cl = null;
        try {
            cl = TClass.class(替换成你要调用的class);
            Object Clazz = cl.newInstance();
            Method m1 = cl.getDeclaredMethod("methonName"(方法名),String(参数类型).getClass);
            m1.setAccessible(true);
            Object invoke = m1.invoke(Clazz,"参数"(参数));
            return invoke;
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }
}

总结

用反射的机制去映射出一个类,然后去调用它的私有方法,因为反射可以把私有方法也映射出来。

作者的话

互相尊重,互相进步,很感谢大家的无私精神。才能让我们中国IT越来越进步!

也非常愿意虚心听取更多大佬的意见和建议,和大家一起交流进步。

我是 樊亦凡

一个每天进步一点点的程序猿

一个不甘愿靠颜值吃饭的程序猿

==您的点赞是我最好的鼓励!非常感谢!==

在这里插入图片描述