java - 如何限制 Java ServiceLoader 仅加载测试包中定义的服务提供者
问题描述
我有一个使用 ServiceLoader 的应用程序。
有一个服务接口 MyFancyService 及其实现:AppClassA、AppClassB 和测试实现:TestClassC、TestClassD
应用包中有 META-INF.services,测试包中有另一个 META-INF.services。
应用程序中的 META-INF.services 指向提供程序类 AppClassA 和 AppClassB
测试点中的 META-INF.services 指向提供程序类 TestClassC 和 TestClassD
运行应用程序时,ServiceLoader.load(MyFancyService.class))
仅加载AppClassA
, AppClassB
. 显然,类路径中没有测试类,这就是原因。我理解这一点,这是可取的
在运行测试时,ServiceLoader.load(MyFancyService.java)) 会加载所有类 AppClassA、AppClassB、TestClassC、TestClassD。
有没有办法限制服务加载器在运行测试时只TestClassC
加载TestClassD
?
解决方案
当测试运行时,它在类路径中同时具有“测试”和“生产”类/资源。这就是加载所有四个服务的原因,这是一种理想的行为,您显然需要 test 和 prod 类路径。
因此,最重要的是,您有两个选择:
选项1
使用类似 PowerMock/PowerMockito 的工具来模拟静态方法ServiceLoader.load
。我自己没有尝试过,但总的来说,除非它是某种遗留代码,否则我不建议使用它。
选项 2
重构代码并模拟对服务加载器的调用,如下所示:
inteface MyServiceLoader {
void loadMyStuff(Class<?> type);
}
class MyServiceLoaderImpl implements MyServiceLoader {
public void loadMyStuff(Class<?> type() {
ServiceLoader.load(type);
}
}
// and now in ClassUnderTest:
public class ClassUnderTest {
private MyServiceLoader myServiceLoader;
public void thisIsAMethodToTest() {
...
myServiceLoader.loadMyStuff(MyFancyInterface.class);
}
}
在测试中,您可以使用 mockito 模拟接口MyServiceLoader.loadMyStuff
并仅加载测试实现。
推荐阅读
- jquery - 使用 AJAX 存储 cookie 的 jQuery 不起作用
- c# - ViewModel 有三个不同的表,如何通过 lambda 将三个表连接成一个结果?
- javascript - 如何在 Angular8 中创建通用请求服务
- bash - 使用终端中的 bash 脚本从 csv 中回显变量和字符串
- java - 为什么不需要使用泛型内部类进行参数化?
- python - 在没有线程执行器的情况下运行 Python gRPC 服务器
- sql-server - Power BI 中是否有雪球般的机会从 SQL Server 表中加载 DAX 逻辑?
- windows - 是否可以使用批处理编程在命令提示符下输出当前颜色代码?
- bash - bash:如何获得
在“cat”创建文件命令的内容中 - tensorflow - 在构建 tf_estimator 时面临 tensorflow2.0 中的错误