testable-mock
testable-mock copied to clipboard
no unique public constructor for [org.elasticsearch.transport.Netty4Plugin]
项目框架:springboot 1.5.9 测试用例
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring-config.xml") public class XxMapperTest { @Resource private XxMapper xxMapper; @Test public void test_get_xx() { Entity entity=new Entity(); entity.setA(System.currentTimeMillis()); entity.setB(1); xxMapper.insert(entity); Entity queryEntity= xxMapper.getXx(entity.getA(), entity.getB()); logger.error("queryEntity---"+ JSON.toJSONString(queryEntity)); Assert.assertTrue(entity.getA().equals(queryEntity.getA())); Assert.assertTrue(entity.getB().equals(queryEntity.getB())); }
}
说明:项目中有引入es框架
报错:
Caused by: java.lang.IllegalStateException: no unique public constructor for [org.elasticsearch.transport.Netty4Plugin]
at org.elasticsearch.plugins.PluginsService.loadPlugin(PluginsService.java:543)
at org.elasticsearch.plugins.PluginsService.
private Plugin loadPlugin(Class extends Plugin> pluginClass, Settings settings, Path configPath) { Constructor>[] constructors = pluginClass.getConstructors(); if (constructors.length == 0) { throw new IllegalStateException("no public constructor for [" + pluginClass.getName() + "]"); } else if (constructors.length > 1) { throw new IllegalStateException("no unique public constructor for [" + pluginClass.getName() + "]"); } else { Constructor<?> constructor = constructors[0]; if (constructor.getParameterCount() > 2) { throw new IllegalStateException(this.signatureMessage(pluginClass)); } else { Class[] parameterTypes = constructor.getParameterTypes();
try {
if (constructor.getParameterCount() == 2 && parameterTypes[0] == Settings.class && parameterTypes[1] == Path.class) {
return (Plugin)constructor.newInstance(settings, configPath);
} else if (constructor.getParameterCount() == 1 && parameterTypes[0] == Settings.class) {
return (Plugin)constructor.newInstance(settings);
} else if (constructor.getParameterCount() == 0) {
return (Plugin)constructor.newInstance();
} else {
throw new IllegalStateException(this.signatureMessage(pluginClass));
}
} catch (ReflectiveOperationException var8) {
throw new IllegalStateException("failed to load plugin class [" + pluginClass.getName() + "]", var8);
}
}
}
}
你的分析是正确的。
从原理来说,当omni.constructor.enhance.enable
配置开启以后,Testable就会为所有待构造的类自动加上一个参数为java.lang.Void
的构造方法,用于避开原类型里可能导致抛异常的默认构造方法。由于这个修改必须在类型首次加载的时候进行,因而Testable无法等到执行OmniConstructor.newInstance()
再来按需添加,默认会给所有类都加上,但遇到某些框架不允许类型有多个构造方法的时候就会出问题。
解决办法是在testable.properties
配置文件里添加以下内容,显式指定不要处理ElasticSearch插件相关的类型:
omni.constructor.enhance.pkgPrefix.excludes = org.elasticsearch.transport,org.elasticsearch.plugin
具体可参考全局运行参数文档。
这个问题我会近期补充到文档的常见使用问题里,在下个版本里也会增加对ElasticPlugin这种特例情况的适配。
感谢反馈。