我有这个非常有趣的问题让我在过去的两天里把头发拆掉了。
我正在使用 jUnit 和嵌入式Tomcat 来测试一些API端点( Jersey )。 我不是嘲笑的忠实粉丝,我做了这个设置来测试API响应,条件尽可能接近生产。
当API收到呼叫时,它应该相应地提供响应(找到,找不到等)。这就是 Hibernate 的用武之地。
当我在eclipse中设置的Tomcat上运行它时,或者当我在远程服务器上的独立Tomcat上部署构建(Maven)时,一切正常,但是在测试期间在嵌入式Tomcat上调用API时我收到这个错误:
java.lang.ClassCastException:com.models.listing.Listing不能 强制转换为com.models.listing.Listing
是的,它是同一个类名。
要检索Listing对象,我使用Hibernate标准来获取ID
的持久化对象Listing listing = session.get(Listing.class, ID);
这是嵌入式tomcat设置的样子:
public void start(String appName) throws Exception {
File root = getRootFolder();
System.setProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE", "true");
Path tempPath = Files.createTempDirectory("tomcat-base-dir");
tomcat = new Tomcat();
tomcat.setPort(0);
tomcat.enableNaming();
tomcat.setSilent(true);
tomcat.setBaseDir(tempPath.toString());
tomcat.getHost().setDeployOnStartup(true);
tomcat.getHost().setAutoDeploy(true);
tomcat.getHost().setAppBase(tempPath.toString());
File webContentFolder = new File(root.getAbsolutePath(), "src/main/webapp/");
if (!webContentFolder.exists()) {
webContentFolder = Files.createTempDirectory("default-doc-base").toFile();
}
StandardContext ctx = (StandardContext) tomcat.addWebapp("/" + appName, webContentFolder.getAbsolutePath());
//Disable TLD scanning by default
if (System.getProperty(Constants.SKIP_JARS_PROPERTY) == null ) {
System.out.println("disabling TLD scanning");
StandardJarScanFilter jarScanFilter = (StandardJarScanFilter) ctx.getJarScanner().getJarScanFilter();
jarScanFilter.setTldSkip("*");
}
System.out.println("configuring app with basedir: " + webContentFolder.getAbsolutePath());
// Declare an alternative location for your "WEB-INF/classes" dir
// Servlet 3.0 annotation will work
File additionWebInfClassesFolder = new File(root.getAbsolutePath(), "target/classes");
WebResourceRoot resources = new StandardRoot(ctx);
WebResourceSet resourceSet;
if (additionWebInfClassesFolder.exists()) {
resourceSet = new DirResourceSet(resources, "/WEB-INF/classes", additionWebInfClassesFolder.getAbsolutePath(), "/");
System.out.println("loading WEB-INF resources from as '" + additionWebInfClassesFolder.getAbsolutePath() + "'");
} else {
resourceSet = new EmptyResourceSet(resources);
}
resources.addPreResources(resourceSet);
ctx.setResources(resources);
//start tomcat
tomcat.start();
}
这就是Hibernate配置的样子:
private static SessionFactory buildSessionFactory() {
// setup the session factory
Configuration configuration = new Configuration();
//add annotated classes
configuration.addAnnotatedClass(Listing.class);
//connection properties
configuration.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
configuration.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
configuration.setProperty("hibernate.connection.url", "jdbc:mysql://<some IP>:3306/<some db name>");
configuration.setProperty("hibernate.connection.release_mode", "auto");
configuration.setProperty("hibernate.connection.username", "<some username>");
configuration.setProperty("hibernate.connection.password", "<some password>");
configuration.setProperty("hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
//sql properties
configuration.setProperty("show_sql", "true");
configuration.setProperty("format_sql", "true");
//misc properties
configuration.setProperty("hibernate.hbm2ddl.auto", "validate");
configuration.setProperty("hibernate.current_session_context_class", "thread");
//c3p0 properties
configuration.setProperty("hibernate.c3p0.min_size", "1");
configuration.setProperty("hibernate.c3p0.max_size", "10");
configuration.setProperty("hibernate.c3p0.timeout", "100");
configuration.setProperty("hibernate.c3p0.max_statements", "50");
configuration.setProperty("hibernate.c3p0.idle_test_period", "1000");
configuration.setProperty("hibernate.c3p0.validate", "true");
//return null
return configuration.buildSessionFactory();
}
总而言之,测试在jUnit中启动,嵌入式tomcat实例启动,并且使用REST客户端向API端点发送请求。端点在从Hibernate检索资源后响应。
依赖版本:
Glassfish Jersey 2.23
jUnit 4.11
Tomcat嵌入式8.5.3
Hibernate 5.2.1
我最好的选择是类加载器的一些问题。 我知道JVM看到类不同,如果它们加载了不同的类加载器,即使它基本上是同一个包中的同一个类,依此类推,但我似乎没有办法让这个工作。
也许我的假设是完全关闭的,我在这里遗漏了一些东西,所以如果有人遇到过这样的事情或有一些建议(我已经尝试了几十个“解决方案”),请跳进去。
提前感谢大家的帮助!
答案 0 :(得分:2)
我仍然没有弄清楚这个谜团,我只是放弃了一些其他的“试错法”与类加载器的想法等等。
我通过降级到休眠4.3.11来“修复”它。