TestNG and Spring 3
Asked Answered
M

5

6

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>
Monika answered 30/9, 2009 at 11:42 Comment(1)
SPring's testing support is for integration testing, not unit testing. You can use plain JUnit or TestNG for unit testing. So what testing are you actually trying to achieve?Slideaction
J
5

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");

?

Jit answered 30/9, 2009 at 13:11 Comment(7)
So if I give the test an empty context I can run a test that includes Class.forName, that gives me: java.lang.IncompatibleClassChangeError: class org.hibernate.cfg.ExtendedMappings has interface org.hibernate.cfg.Mappings as super class But when I run the same in my servlet context, I don't have a problem. And they have the same classpath.Monika
I believe the only place ExtendedMappings is defined in any of my jar-files is in hibernate-annotations.jar.Monika
Hmm, this may be because I'm running Hibernate 3.5-beta1 with Hibernate-Annotations 3.4. Let me try and downgrade to 3.4 and see if they're more aligned then :-)Monika
When looking at: fisheye.jboss.org/browse/Hibernate/core/trunk/core/src/main/… you can see that org.hibernate.cfg.Mappings is an interface in one of the versions (15365) and a class in other (11588). That confirms the suspicion of wrong Hibernate JARs being used.Jit
Err... 3.4 doesn't exist. So I'll give Hibernate Core 3.3.2 with Hibernate Annotations 3.4 a tryMonika
You may find useful the Compability Matrix of Hibernate modules: hibernate.org/6.html#A3 .Jit
Thanks a bunch. You are, of course, very correct in your suspicion. Going back to 3.3.2 aligned core and annotations again. :-)Monika
U
7

Your test ckass needs to extend AbstractTestNGSpringContextTests. Or if your code is testing database acces another useful class to extend is AbstractTransactionalTestNGSpringContextTests.

Uropygium answered 30/9, 2009 at 11:47 Comment(2)
Thanks you very much. Extending AbstractTestNGSpringContextTests made it load the context, but it gives me a strange exception while initializing. I've updated my question with the exceptions it gives to my contextMonika
Please vote this up as it is the answer to the original question and is what I was looking for (eg: Using Spring with TestNG )Dilemma
J
5

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");

?

Jit answered 30/9, 2009 at 13:11 Comment(7)
So if I give the test an empty context I can run a test that includes Class.forName, that gives me: java.lang.IncompatibleClassChangeError: class org.hibernate.cfg.ExtendedMappings has interface org.hibernate.cfg.Mappings as super class But when I run the same in my servlet context, I don't have a problem. And they have the same classpath.Monika
I believe the only place ExtendedMappings is defined in any of my jar-files is in hibernate-annotations.jar.Monika
Hmm, this may be because I'm running Hibernate 3.5-beta1 with Hibernate-Annotations 3.4. Let me try and downgrade to 3.4 and see if they're more aligned then :-)Monika
When looking at: fisheye.jboss.org/browse/Hibernate/core/trunk/core/src/main/… you can see that org.hibernate.cfg.Mappings is an interface in one of the versions (15365) and a class in other (11588). That confirms the suspicion of wrong Hibernate JARs being used.Jit
Err... 3.4 doesn't exist. So I'll give Hibernate Core 3.3.2 with Hibernate Annotations 3.4 a tryMonika
You may find useful the Compability Matrix of Hibernate modules: hibernate.org/6.html#A3 .Jit
Thanks a bunch. You are, of course, very correct in your suspicion. Going back to 3.3.2 aligned core and annotations again. :-)Monika
J
1

Consult the chapter on TestNG in the Spring documentation:

Jit answered 30/9, 2009 at 11:47 Comment(1)
Don't worry, I only wrote here after reading "Spring TestContext Framework" in the Spring 3 Reference manual twice and reading quite a few tutorialsMonika
P
1

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.

Portaltoportal answered 3/6, 2011 at 6:10 Comment(0)
S
0

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.

Stuartstub answered 1/11, 2009 at 3:18 Comment(2)
If you're using hibernate-core-3.5.x, it should include the annotations (and entityManager) - separate jars no longer required according to hibernate hibernate.org/397.htmlSergio
That's what i thought, but I still need to pull annotations in. If you look at hibernate-annotations pom it has hibernate-core as a dependency. What i think hibernate means is that the version numbers are aligned. Or have I been drinking too much beer :)Stuartstub

© 2022 - 2024 — McMap. All rights reserved.