如何通过子类测试父类私有方法(PrivateMethodTester与继承)
解决子类测试父类私有方法的问题
首先得明确为什么你会遇到这个报错:父类的private方法是完全封装在父类内部的,子类根本继承不到这个方法,所以你用PrivateMethod[MyChild]('myMethod)去子类里找这个方法,自然会找不到。
下面给你几个可行的解决方案,你可以根据实际场景选择:
方案1:利用测试框架指定方法所属的父类
如果你用的是ScalaTest的PrivateMethodTester,其实不需要修改源代码,只需要在调用的时候明确指定方法属于父类MyParent就行。调整后的测试代码如下:
val c = new MyChild() // 声明方法的返回值类型为Int,方法名为myMethod val m = PrivateMethod[Int]('myMethod) // 调用时指定方法来自MyParent类 assertEquals(12, c invokePrivate m()(classOf[MyParent]))
这个方案的好处是完全不需要修改业务代码,只调整测试逻辑就能实现需求。
方案2:修改父类方法权限+子类包装(你提到的方案)
如果允许修改父类的代码,可以把父类的private方法改成protected,这样子类就能访问到,然后在子类里加一个包装方法:
// 修改后的父类 class MyParent { protected def myMethod() = 12 } // 子类添加包装方法 class MyChild extends MyParent { private def wrapMyMethod() = super.myMethod() }
然后测试的时候直接调用子类的wrapMyMethod即可:
val c = new MyChild() val m = PrivateMethod[Int]('wrapMyMethod) assertEquals(12, c invokePrivate m())
这个方案的代码更符合Scala的封装规范,但属于侵入式修改,如果你没法修改父类(比如父类是第三方依赖),这个方案就不适用。
方案3:直接用Java反射调用
如果上面两种方案都不适合,还可以直接用Java反射绕过封装,直接调用父类的私有方法:
val c = new MyChild() // 获取父类的私有方法 val method = classOf[MyParent].getDeclaredMethod("myMethod") // 开启方法的可访问性 method.setAccessible(true) // 调用方法,传入子类实例(因为子类实例包含父类的实例部分) val result = method.invoke(c).asInstanceOf[Int] assertEquals(12, result)
这个方案不需要修改任何业务代码,兼容性也强,但反射代码相对繁琐,而且如果父类方法签名变化,测试代码可能会悄无声息地失败,需要额外注意维护。
内容的提问来源于stack exchange,提问作者Wonay
相关产品推荐
相关产品推荐

