You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 11:48:08