在IntelliJ中跨包调用私有/受保护方法写单元测试及测试目录问题
我来帮你搞定这两个问题——先解决IntelliJ 2016.1.4里测试目录创建的问题,再教你怎么跨包调用私有/受保护方法写单元测试:
一、在IntelliJ IDEA 2016.1.4中创建测试目录
之前的方案失效可能是因为版本操作路径有变化,你可以试试这两种可靠的方法:
方法1:通过模块设置配置(最稳妥)
- 打开项目后,在Project视图里找到你的主源码目录(比如
main/java),右键点击它所属的模块(或者直接右键项目根目录),选择Open Module Settings(快捷键F4也能打开)。 - 在弹出的
Module Settings窗口中,切换到Modules标签页,选中你的目标模块。 - 点击右侧的
Sources标签,在左侧目录结构里找到你要设置的测试文件夹:如果还没创建,先在test目录下新建java文件夹。 - 选中这个
java文件夹,点击窗口上方的Test Sources图标(带绿色对勾的文件夹,悬停提示Mark directory as: Test Sources Root)。 - 点击
Apply再OK,这个目录就会被标记为测试源码根目录,IntelliJ会自动识别这里的测试类。
方法2:快捷右键设置
- 在Project视图里找到
test目录,右键选择New > Directory,命名为java。 - 右键这个新建的
java文件夹,选择Mark Directory as > Test Sources Root,一步完成设置。
二、跨包调用私有/受保护方法编写单元测试
针对你提供的MyApp类,这里有两种实用方案:
方案1:用Java反射(无需额外依赖)
反射是Java自带的能力,能直接访问私有成员。假设你的MyApp类完整代码如下:
package main.java.com.simpleproject; public class MyApp { private int updNum; public MyApp(int givenNum){ this.updNum = givenNum; } private void updateNum(int newNum){ this.updNum = newNum; } }
对应的单元测试可以这么写:
package test.java.com.simpleproject; // 和主类保持同包结构的测试包 import main.java.com.simpleproject.MyApp; import org.junit.Test; import java.lang.reflect.Method; import java.lang.reflect.Field; public class MyAppTest { @Test public void testPrivateUpdateNum() throws Exception { MyApp app = new MyApp(10); // 获取私有方法:参数是方法名+参数类型 Method updateNumMethod = MyApp.class.getDeclaredMethod("updateNum", int.class); // 取消访问检查,允许调用私有方法 updateNumMethod.setAccessible(true); // 调用方法:第一个参数是实例对象,后面是方法参数 updateNumMethod.invoke(app, 20); // 验证私有字段的变化(同样用反射) Field updNumField = MyApp.class.getDeclaredField("updNum"); updNumField.setAccessible(true); int currentNum = (int) updNumField.get(app); // 断言结果符合预期 assert currentNum == 20; } }
方案2:用PowerMock框架(适合复杂场景)
如果需要频繁调用私有方法或者模拟私有方法行为,PowerMock是个不错的选择,它和JUnit兼容很好:
- 先在Maven的
pom.xml中添加依赖(适配JUnit 4):
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.7.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.7.4</version> <scope>test</scope> </dependency>
- 编写测试类:
package test.java.com.simpleproject; import main.java.com.simpleproject.MyApp; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(MyApp.class) public class MyAppPowerMockTest { @Test public void testPrivateUpdateNum() throws Exception { MyApp app = new MyApp(10); // 直接调用私有方法 PowerMockito.invokePrivate(app, "updateNum", 20); // 获取私有字段的值 int currentNum = PowerMockito.field(MyApp.class, "updNum").get(app); // 断言结果 assert currentNum == 20; } }
内容的提问来源于stack exchange,提问作者Fiddle Freak
相关产品推荐
相关产品推荐

