33

When attempting to combine the Spring test runner and the PowerMock runner using the PowerMockRule technique, I get an exception from the Thoughtworks XStream library whenever I try to inject an EntityManager using the PersistenceContext annotation from JPA. The same test works fine when not using the PowerMockRule. I also ignore all packages from the PowerMockLoader at the start of the test. I tried various values for @PowerMockIgnore as this normally solves issues I have with PowerMock, however, this error still happens even when ignoring absolutely every package.

@PowerMockIgnore("*")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-configuration.xml")
public class SpringAndPowerMockTest {
    @Rule
    public PowerMockRule rule = new PowerMockRule();

    @PersistenceContext
    private EntityManager manager;

    @Test
    public void test() {
    }
}

The exception is as follows -- links to full backtrace on pastebin the backtrace exceeded the limit for question length):

com.thoughtworks.xstream.converters.ConversionException: Could not call org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.readObject() : Could not call java.util.concurrent.CopyOnWriteArrayList.readObject() : Could not call java.security.CodeSource.readObject() : null

Relevant persistence unit:

<persistence-unit name="inMemory">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>

  <properties>
    <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
    <property name="hibernate.connection.url" value="jdbc:h2:mem:InMemoryUnitTests;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE" />
    <property name="hibernate.connection.username" value="sa" />
    <property name="hibernate.connection.password" value="" />
    <property name="hibernate.hbm2ddl.auto" value="create-drop" />
  </properties>
</persistence-unit>

Maven dependencies:

<dependencies>
<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>1.5.1</version>
        <scope>test</scope>
</dependency>
<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito</artifactId>
        <version>1.5.1</version>
        <scope>test</scope>
</dependency>
<dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>1.9.5</version>
        <scope>test</scope>
</dependency>
<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-easymock</artifactId>
        <version>1.5.1</version>
        <scope>test</scope>
</dependency>
<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4-rule</artifactId>
        <version>1.5.1</version>
        <scope>test</scope>
</dependency>
<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-classloading-xstream</artifactId>
        <version>1.5.1</version>
        <scope>test</scope>
</dependency>
</dependencies>

Testing using Spring 3.2.3.RELEASE. Note that I have also tested with spring-test version 3.0.5.RELEASE which does indeed resolve some other errors with the Spring/Powermock combination, but not this one.

amoe
  • 4,473
  • 4
  • 31
  • 51
  • What version of XStream are you using? Do you have any custom XStream converters registered? I experienced a problem where I had a custom XStream converter. Custom converters get invoked before other converters, but since I was subclassing the XStream supplied MapConverter whose canConvert method is not null safe I was getting a null pointer exception (normally the NullConverter is at the top of the list). Solution was to make my custom converter's canConvert method null-safe. But judging from your stack traces this looks like something else... – Justin Rowe Jul 17 '13 at 10:18
  • The xstream version resolves transitively to 1.4.2 through the `powermock-classloading-xstream` dependency. I don't have any other code except for the test shown, so don't have any custom converters... – amoe Jul 17 '13 at 10:39
  • 1
    In my experience with Powermock 1.5, it is not compatible with Xstream 1.4.2, I haven't been able to track down the cause; odd then that that is what powermock-classloading-xstream resolves to. I suggest to try adding XStream 1.2.2 as a direct dependency in your pom. – Justin Rowe Jul 19 '13 at 12:53
  • Using an explicit dependency on xstream 1.2.2 changes the error message to `com.thoughtworks.xstream.converters.ConversionException: Cannot construct org.powermock.modules.junit4.rule.PowerMockStatement$1 as it does not have a no-args constructor`. – amoe Jul 19 '13 at 13:53
  • Probably you don't like to hear that, but: what else is to be expected when using PowerMock? For me, "we need PowerMock" normally translates "we have a broken design and want to use the big hammer to test it". Whereas the one and only answer is: fix the broken design, and test it using frameworks that are not famous for creating such bizarre problems. – GhostCat Jul 06 '16 at 13:29

1 Answers1

1

I had a similar issue and it was suggested to me to create a Resources.java class that Produced an Entity Manager.

@Stateful
public class Resources implements Serializable {

    @PersistenceContext (type = PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;

    @Produces
    public EntityManager getEntityManager() {
        return entityManager;
    }

}

I'm still not exactly sure why this solution worked for me... but it did.

v/r Ace

AceFunk
  • 684
  • 1
  • 8
  • 14