DBUnit - 休眠 - org.hibernate.HibernateException: 无法实例化方言 class

DBUnit - Hibernate - org.hibernate.HibernateException: could not instantiate dialect class

我尝试使用 JUNit、DBUnit 和 Hibernate 对我的 class 进行集成测试。

用于数据库的初始化

为了模拟一个孤立的数据库,我使用了这个 tutorial

请注意,我必须根据允许我设置 hibernate.test.cfg.xml 所在位置的教程创建两个 HibernateUtil class(一个(名为 HibernateUtils.class),另一个(名为 HibernateSessionFactory,它基于 hibernate.cfg.xml )

创建了 SessionFactory

集成测试

我必须测试 Player.class 中的 show_Potions() 方法。

show_Potions() 根据数据库查询设置玩家的药水。我希望测试在隔离数据库而不是真实数据库中进行查询,所以我继续这样做:当使用 HibernateSessionFactory.configureSessionFactory() 时,我们使用 'HibernateUtils.newSessionFactory("hibernate.test.cfg.xml")`.

我遇到了异常:

 org.hibernate.HibernateException: Could not instantiate dialect class
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:82)
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:64)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:146)
at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:71)
at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2277)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2273)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1742)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1782)
at test.HibernateUtils.newSessionFactory(HibernateUtils.java:27)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:132)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:95)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassCastException: org.hibernate.dialect.HSQLDialect cannot be cast to org.hibernate.dialect.Dialect
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:73)
... 37 more

java.lang.NullPointerException
at test.HibernateDbUnitTestCase.tearDown(HibernateDbUnitTestCase.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.MethodRoadie.runAfters(MethodRoadie.java:149)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:101)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

您可以看到下面的代码。

感谢您的回复。如果您有其他访问隔离数据库的方法,我将很高兴听到。


Player.class

public class Player extends TablePlayer {

    private List<Item> items;

    //other attributes…

    /*
     * This method set the list of potions of the player based on the query from the database.
     */

    public void show_Potions() throws Exception {

        SessionFactory sf = HibernateSessionFactory.configureSessionFactory();
        Session session = sf.getCurrentSession();
        session.getTransaction().begin();

        try {

            StringBuilder query = new StringBuilder();
            query.append("from TableItems items " +
                    "left join fetch items.name " +
                    "left join fetch items.type " +
                    "left join fetch items.idPlayer player " +
                    "where player.id = :pid ");
            query.append("order by items.dateObtained desc");

        List<TableItems> tableItems = session.createQuery(query.toString()).setParameter(“pid”, this.getId()).list();

        List<Item> potions = new ArrayList<Items>();

        for(TableItems tItem : tableItems){
            Item item = new Item(tItem);
            if(item.getType()).equals(“POTION”){
                potions.add(item);
            }       
        }

        this.setItems( potions );

        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        } finally {
            session.clear();
            session.close();
        }       
    }

    /*
     *  Constructor
     */


    public Player(String id) { // Create a player based on the ID found in the Database
    }

    // other methods...

}

玩家测试

@RunWith(PowerMockRunner.class)
@PrepareForTest(HibernateSessionFactory.class)
public class PlayerTest extends HibernateDbUnitTestCase {

    private Player player
    private Player player_to_spy;
    private List<Item> actual_items;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        player_to_spy = new Player(“1”);
        player = spy(player_to_spy);
        actual_items = new ArrayList<Item>();
    }

    protected IDataSet getDataSet() throws Exception {  
           return new FlatXmlDataSet(this.getClass().getResourceAsStream("/test/database.xml"));
        }  


    @Test
    public void testShow_Potions() throws Exception {

        PowerMockito.mockStatic(HibernateSessionFactory.class);
        Mockito.when(HibernateSessionFactory.configureSessionFactory()).thenReturn(sessionFactory);     // sessionFactory is an attribute of HibernateDbUnitTestCase
        Mockito.when(HibernateSessionFactory.configureSessionFactory().getCurrentSession()).thenReturn(session); //session is an attribute of HibernateDbUnitTestCase

        player.setId(“1”);      
        player.show_Potions();
        actual_items = player.getItems(); // return the list of items.

        List<Items> expected_items = new ArrayList<Items>();

        Item item1 = new item(“1”); // create an Item of id n°1 based on the database
        expected_items.add(item1);

        assertThat(actual_items,isEqualTo(expected_items)); // I’ve written the isEqualTo() method.
    }

    @After
    public void destroy() throws Exception {
        player_to_spy = null;
        player = null
        actual_items = null;
    }
}

错误消息非常明确地说明了问题所在。

检查您的配置并确认您已正确配置方言并且它指向正确的方言 class 名称。如果是,请确保方言确实在 class 路径上(如果它是自定义方言实现)。

我终于找到了这个问题的解决方案。

问题是我在测试中创建了两个 SessionFactory。 即:当我在测试中调用 show_potions() 时,我调用 HibernateSessionFactory.configureSessionFactory()。但是,该测试扩展了 HibernateDBUnitTestCase,其 setUp() 方法调用 HibernateUtils.newSessionFactory()。因此,测试不知道它应该使用什么休眠配置。

使用这种方法,您将不需要 PowerMock,您必须使用 JUnit3,因为 DBunit 是基于它的。因此,您必须根据 Junit3 中的要求更改@Test、@Before 和@After。

我就是这样解决问题的。

1)修改HibernateSessionFactory:

初始版本为:

public class HibernateSessionFactory {

private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;


static {
    try {
        // Create sessionFactory based on hibernate.cfg.xml
        Configuration configuration = new Configuration();
        configuration.configure();
        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);

    } catch (Throwable ex) {
        System.err.println("Initial SessionFactory creation failed. " + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static SessionFactory configureSessionFactory() throws HibernateException {
    return sessionFactory;
}

}

删除了静态块并使用以下内容更改了 configureSessionFactory()

public static SessionFactory configureSessionFactory() throws HibernateException {
    if(sessionFactory == null) {
        try{
            Configuration configuration = new Configuration();
            configuration.configure();
            serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed. " + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
    return sessionFactory;
}

我也添加了这个方法。

public static void setSessionFactory(SessionFactory factory) 
{ 
    HibernateSessionFactory.sessionFactory = factory; 
} 

2)修改HibernateDbUnitTestCase

在设置中,我添加了以下行:

if (sessionFactory == null) {  
        sessionFactory = HibernateUtils.newSessionFactory("hibernate.test.cfg.xml");  
        HibernateSessionFactory.setSessionFactory(sessionFactory);

    } 

就是这样,每当 'real' 程序调用 show_potions()HibernateSessionFactory.configureSessionFactory() 使用 "hibernate.cfg.xml",当测试程序调用 show_potions,它使用 "hibernate.test.cfg.xml".

希望对其他人有所帮助。