单元测试中如何无需修改权限测试private/fileprivate函数?
无需修改权限,测试private/fileprivate函数的实用方案
嘿,这个问题我之前踩过坑,太懂那种要测私有函数又不想改权限的纠结了!不用把private改成public或者internal,完全有办法搞定,而且不同主流语言都有对应的实操方案,我给你捋捋:
核心思路:用反射绕开访问限制
几乎所有静态类型语言都支持反射(Reflection),它能让你在运行时直接获取类的私有成员并调用,这是最通用的解决方案。下面是几种常见语言的具体做法:
1. Swift(针对private/fileprivate)
Swift的访问控制比较严格,但也有两种常用方式:
- 如果你的
Manager类继承自NSObject:
直接用Objective-C的Runtime特性,通过perform(_:with:)调用私有方法,注意selector的命名要符合OC的桥接规则:
这里要注意,Swift的函数名会被桥接成OC风格,比如let manager = Manager() // 调用无参私有函数privateFunc() manager.perform(Selector(("privateFunc"))) // 调用带参数的私有函数privateFunc(with: String) manager.perform(Selector(("privateFuncWith:")), with: "test input")privateFunc(with:)会变成privateFuncWith:,多参数的情况要对应好命名。 - 纯Swift类(不继承NSObject):
可以给私有函数加上@objc dynamic修饰,这样就能用上面的Selector方法调用——这个方法简单,而且不用修改权限,只是多加个修饰符而已;也可以用Mirror解析类的私有成员,但操作会繁琐一些。
2. C#
C#的反射非常直接,步骤清晰明了:
// 获取Manager类的Type对象 Type managerType = typeof(Manager); Manager managerInstance = new Manager(); // 找到目标私有方法,BindingFlags要包含Instance和NonPublic MethodInfo privateMethod = managerType.GetMethod( "PrivateFuncName", BindingFlags.Instance | BindingFlags.NonPublic ); // 调用方法,第一个参数是实例对象,后面是方法需要的参数 privateMethod.Invoke(managerInstance, new object[] { "param1", 2 });
如果是静态私有方法,把BindingFlags.Instance换成BindingFlags.Static就行。
3. Java
Java的反射也很成熟,关键是要调用setAccessible(true)绕过权限检查:
Manager manager = new Manager(); Class<?> managerClass = manager.getClass(); // 获取指定参数类型的私有方法 Method privateMethod = managerClass.getDeclaredMethod( "privateFunc", String.class, int.class ); // 取消访问权限检查 privateMethod.setAccessible(true); // 调用方法,传入实例和参数 privateMethod.invoke(manager, "test", 123);
4. Objective-C
Objective-C本身就是动态语言,调用私有方法毫无压力,直接用performSelector:就行:
Manager *manager = [[Manager alloc] init]; // 调用无参私有方法 [manager performSelector:@selector(privateFunc)]; // 调用带参数的私有方法 [manager performSelector:@selector(privateFuncWithParam:) withObject:@"test"];
题外话:要不要直接测私有函数?
技术上完全可行,但我还是想多嘴一句:如果经常需要直接测私有函数,可能意味着你的公共函数职责太臃肿,或者私有函数的逻辑其实可以拆成独立的工具类(改成internal/public),这样测试会更优雅。不过如果确实是因为测试公共函数的前置准备成本太高(比如要造一堆复杂的依赖数据),那用反射测试私有函数绝对是合理的选择。
内容的提问来源于stack exchange,提问作者Klein Mioke
相关产品推荐
相关产品推荐

