JUnit未命名模块中ResourceBundleControlProvider的getControl方法未被调用的问题
JUnit未命名模块中ResourceBundleControlProvider的getControl方法未被调用的问题
我遇到了一个奇怪的问题:当在JUnit环境下运行未命名模块中的测试程序时,自定义的ResourceBundleControlProvider的getControl()方法完全没被触发,但直接运行程序的main方法时却能正常工作。下面是详细的情况:
问题详情
我实现了一个ResourceBundleControlProvider来拦截资源包的加载过程,直接运行程序时,调用ResourceBundle.getBundle()会触发这个provider的getControl()方法,控制台能看到对应的输出;但用JUnit运行测试方法时,虽然ServiceLoader能找到这个provider实例,getControl()却始终没被调用,完全没有对应的日志输出。
代码实现
1. 自定义ResourceBundleControlProvider实现
import java.util.ResourceBundle; import java.util.spi.ResourceBundleControlProvider; /** * A ResourceBundleControlProvider implementation */ public class MyControlProvider implements ResourceBundleControlProvider { public ResourceBundle.Control getControl(String baseName) { System.out.println("In getControl, baseName: " + baseName); return null; } }
2. SPI配置文件
在META-INF/services/java.util.spi.ResourceBundleControlProvider文件中添加如下内容:
MyControlProvider
3. JUnit测试类代码
import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.ServiceLoader; import java.util.spi.ResourceBundleControlProvider; import org.junit.jupiter.api.Test; class TestProvider { /** * Attempt to load a missing resource bundle - should throw * MissingResourceException and write a message to stdout. */ @Test public void testProvider() { try { ResourceBundle.getBundle("foo"); } catch(MissingResourceException e) { System.out.println("Caught: " + e.getMessage()); } ServiceLoader<ResourceBundleControlProvider> loader = ServiceLoader.loadInstalled(ResourceBundleControlProvider.class); for (ResourceBundleControlProvider provider : loader) { System.out.println("Found installed provider instance of: " + provider.getClass().getName()); } ServiceLoader<ResourceBundleControlProvider> loader2 = ServiceLoader.load(ResourceBundleControlProvider.class); for (ResourceBundleControlProvider provider : loader2) { System.out.println("Found provider instance of: " + provider.getClass().getName()); } Module mod = this.getClass().getModule(); if (mod.isNamed()) { System.out.println("Module: " + mod.getName()); } else { System.out.println("Unnamed Module: " + mod.toString()); } } public static void main(String[] args) { TestProvider tp = new TestProvider(); tp.testProvider(); } }
运行结果对比
直接运行主类的输出
In getControl, baseName: foo Caught: Can't find bundle for base name foo, locale en_US Found provider instance of: MyControlProvider Unnamed Module: unnamed module @5caf905d
JUnit运行测试的输出
Caught: Can't find bundle for base name foo, locale en_US Found provider instance of: MyControlProvider Unnamed Module: unnamed module @565f390 ✨ Thanks for using JUnit! Support its development at https://junit.org/sponsoring ╷ ├─ JUnit Platform Suite ✔ ├─ JUnit Jupiter ✔ │ └─ TestProvider ✔ │ └─ testProvider() ✔ └─ JUnit Vintage ✔ Test run finished after 188 ms
很明显,JUnit运行时完全没有In getControl, baseName: foo这条输出,说明getControl()根本没被调用。
环境信息
- JUnit Platform Console Launcher: 1.13.0-M2
- JDK: 21.0.6 (Eclipse Adoptium OpenJDK 64-Bit Server VM 21.0.6+7-LTS)
- OS: Mac OS X 15.4.1 aarch64
根据JDK文档,ResourceBundleControlProvider在命名模块中会被忽略,但我的测试类所在的是未命名模块,按道理应该正常工作才对。有没有人遇到过类似的问题,或者知道这是为什么呢?
内容来源于stack exchange
相关产品推荐
相关产品推荐

