问题
What is the best practice way to do unit testing with Spring? I assume the combination TestNG & jmockit with Spring 3 isn't bad, so that's what I'm doing right now, but if I'm off course selecting the tools for my fresh Spring project, please tell me right away. :-)
Anyways, I've created an entity that I want to test, but I'm not sure how to actually run the TestNG from the Spring context. I've created a simple test class
package com.mydomain.data.entities.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.*;
@ContextConfiguration(locations={"classpath:applicationContext.xml"})
public class SimpleTest extends AbstractTestNGSpringContextTests {
@Autowired
private ApplicationContext applicationContext;
@BeforeClass
protected void setUp() throws Exception {
Assert.assertNotNull(applicationContext);
}
@Test
public void testNothing() {
}
}
with applicationContext.xml importing beans for setting up the model and business layer. First off all, I'd like it to use the applicationContext.xml from Project/WebRoot/WEB-INF, whereas the source for this test lives in Project/src/com/mydomain/data/entities/test, but I believe that /applicationContext.xml would give me Projects/src, same as classpath: Is this correct?
Furthermore, now that I'm using the model and business layers that my web application would use, I should expect it to behave similarly. But, when I launch TestNG on the test, it sais: class org.hibernate.cfg.ExtendedMappings has interface org.hibernate.cfg.Mappings as super class:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in URL [file:/Users/niklas/Documents/Eclipse/Project/WebRoot/WEB-INF/Project-Model.xml]: Invocation of init method failed; nested exception is java.lang.IncompatibleClassChangeError: class org.hibernate.cfg.ExtendedMappings has interface org.hibernate.cfg.Mappings as super class
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1393)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:449)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:289)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:286)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:352)
at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:266)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:121)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:77)
at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:70)
at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:99)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1414)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1381)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511)
... 38 more
Caused by: java.lang.IncompatibleClassChangeError: class org.hibernate.cfg.ExtendedMappings has interface org.hibernate.cfg.Mappings as super class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:700)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:319)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:330)
at java.lang.ClassLoader.loadClass(ClassLoader.java:254)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:399)
at org.hibernate.cfg.AnnotationConfiguration.createExtendedMappings(AnnotationConfiguration.java:187)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:277)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1162)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:667)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1452)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1390)
... 53 more
What is this and why am I getting this? Any clues?
My sessionFactory looks like this
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<!-- Entity classes from package com.mydomain.data.entities -->
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
回答1:
Now the problem doesn't seem to be related to any of Spring or TestNG. The key part is:
java.lang.IncompatibleClassChangeError: class org.hibernate.cfg.ExtendedMappings has interface org.hibernate.cfg.Mappings as super class
Are you sure your CLASSPATH is OK? I.e. you have compatible version of Hibernate modules and no repetitions there?
What if you create a simple TestNG test that does the following:
Class.forName("org.hibernate.cfg.ExtendedMappings");
?
回答2:
Your test ckass needs to extend AbstractTestNGSpringContextTests. Or if your code is testing database acces another useful class to extend is AbstractTransactionalTestNGSpringContextTests.
回答3:
Consult the chapter on TestNG in the Spring documentation:
- for Spring 2.5.
- for Spring 3.0
回答4:
For me this problem was caused because I had different hibernate versions included myself, not because of a third party including them. A sweep of your project/poms to make sure you youserlf are only using one hibernate version is worthwhile.
回答5:
You might want to try hibernate-annotations-3.5.0-Beta-1 as this aligns with hibernate-core-3.5.0-Beta-1.
I still get the java.lang.IncompatibleClassChangeError sometimes, as I'm trying to use hibernate search which is using the "old" annotations.
Also, not sure if you are running JBoss, but if you are you'll get this error with core 3.5.0.
来源:https://stackoverflow.com/questions/1497619/testng-and-spring-3