我尝试使用JUNit,DBUnit和Hibernate对我的类进行集成测试。
为了模拟一个孤立的数据库,我使用了这个tutorial。
请注意,我必须根据教程创建两个HibernateUtil类(一个(名为HibernateUtils.class
),这允许我设置hibernate.test.cfg.xml
所在的位置,另一个(名为HibernateSessionFactory
它基于hibernate.cfg.xml
)
我必须从show_Potions()
测试Player.class
方法。
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$1.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$1.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)
您可以看到以下代码。
感谢您的回复。如果您有其他方式可以访问隔离数据库,我很高兴听到它。
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;
}
}
答案 0 :(得分:1)
错误信息非常明确地表明了问题所在。
检查您的配置并验证您是否已正确配置方言,并且它指向正确的方言类名称。如果是,请确保方言实际上在类路径上,如果它是自定义方言实现。
答案 1 :(得分:0)
我最终找到了解决这个问题的方法。
问题是我在测试中创建了两个SessionFactory。
即:当我在测试中致电show_potions()
时,我会拨打HibernateSessionFactory.configureSessionFactory()
。但是,测试扩展了HibernateDBUnitTestCase,其setUp()
方法调用HibernateUtils.newSessionFactory()
。因此,测试不知道它应该使用什么样的hibernate配置。
使用这种方法,你不会需要PowerMock,你必须使用JUnit3,因为DBunit是基于它的。因此,您必须使用Junit3中所需的内容更改@ Test,@ Before和@After。
这就是我解决问题的方法。
初始版本是:
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
在setUp中,我添加了以下行:
if (sessionFactory == null) {
sessionFactory = HibernateUtils.newSessionFactory("hibernate.test.cfg.xml");
HibernateSessionFactory.setSessionFactory(sessionFactory);
}
这就是全部,只要真正的&#39;程序调用{{1}},show_potions()
)使用HibernateSessionFactory.configureSessionFactory(
,当测试程序调用show_potions时,它使用"hibernate.cfg.xml"
。
我希望它能帮助其他人。