添加BNF规则后JUnit测试遭遇java.lang.NoClassDefFoundError异常求助
解决新增BNF规则后JUnit测试抛出
NoClassDefFoundError的问题 我之前在开发IntelliJ插件时也遇到过几乎一模一样的情况——插件运行时一切正常,PSI View里也能看到新增的令牌和元素,但单元测试死活找不到明明存在的PSI实现类。结合你给出的错误信息,给你几个针对性的排查方向:
1. 先搞定编译同步问题
单元测试的类加载器经常会因为旧编译产物残留,找不到最新生成的FooBarImpl:
- 先跑一遍Clean + Rebuild(比如Gradle里执行
clean build,Maven用clean install),彻底清除旧的class文件后重新编译整个项目。 - 检查测试模块的依赖配置,确保它正确依赖了主模块的编译输出。比如Gradle里要确认
testImplementation project(':your-main-plugin-module')已经配置,而且主模块的编译任务会在测试任务之前执行。
2. 重点看错误里的类名拼写!
你注意到报错里的细节了吗?
Caused by: java.lang.ClassNotFoundException: de.foo.bar.psi.impl.FooTinesImpl
而你说实际存在的是FooBarImpl——这十有八九是拼写错误搞的鬼:
- 去翻你的BNF文件,检查对应规则的生成类名配置是不是把
Bar写成了Tines。 - 打开自动生成的
FooTypes.java第424行(错误栈里标了位置),看看它尝试加载的类名到底是什么。如果确实是生成代码写错了,重新运行PSI生成任务(比如Gradle的generatePsi)就能修复。
3. 检查测试的类加载环境
IntelliJ插件测试的类加载器有特殊要求,别用普通的JUnit测试基类:
- 确保你的测试类继承的是IntelliJ官方提供的测试基类,比如
LightPlatformCodeInsightTestCase或者BasePlatformTestCase,这些类会帮你正确初始化插件测试的类加载环境。 - 如果是自定义的测试配置,检查启动参数里的类路径是否包含了主模块的编译产物目录,别漏了。
4. 确认PSI类的访问权限
虽然概率不高,但还是检查下FooBarImpl的访问修饰符是不是public——如果是包级私有,测试模块可能访问不到它,导致类加载失败。
5. 清掉IntelliJ的缓存试试
有时候IDE缓存会抽风,导致编译和运行的类不一致:
- 点
File -> Invalidate Caches...,选"Invalidate and Restart",重启后再重新编译项目和测试。
按这个顺序排查,应该很快能找到问题。我当初遇到的就是拼写错误,BNF里手滑写错了类名,生成的代码就跟着错了,运行时可能因为缓存没爆出来,测试就直接报错了。
内容的提问来源于stack exchange,提问作者common sense
相关产品推荐
相关产品推荐

