-
Notifications
You must be signed in to change notification settings - Fork 238
@Capturing not always able to mock objects. #161
Description
I have encountered an issue when using @capturing. It is related to Spring,Apache CXF, the version of JMockit and also the sequence of running tests.
The issue is very obscure, but I have a concise set of files available that is a full maven project that demonstrates the problem. I have tried to put these at the end of the issue, but can send these if needed.
The business model is:
An interface ITestObject - Containes a single method that helps to identify when the problem arises.
A class TestObjectContainer - A java bean that has a single property of type ITestObject
A class TestObject that implements ITestOject
The testing performed is:
FirstTest - A Junit test class with a single test method that simply loads a spring XML context file first-test.xml and closes the context
SecondTest - A Junit test class with a single test method that
- Has @capturing on ITestObject types
- loads spring XML context file second-test.xml
- Gets a named bean from the context of type TestObjectContainer
- Checks that the contained ITestObject bean is mocked.
The environment is:
Windows 7
Java 8
JUnit 4.12
Spring 4.1.6 Release
JMockit - 1.6 or 1.16 (we had been using 1.6 and tried 1.16 when problems arose)
CXF 3.0.4
Eclipse Luna
Setup A
- JMockit 1.6 (This was the version we were using when we first encountered the problem.
- The first-test.xml configuration has a TestObjectContainer bean containing an ITestObject that is actually a CXF proxy client for a web service.
- The second-test.xml configuration also has a TestObjectContainer bean containing an ITestObject that is actually a CXF proxy client for a web service.
Scenario A1
Run SecondTest on its own - PASS - confirms the ITestObject is mocked.
Scenario A2
Run FirstTest then SecondTest as a single execution (I selected the package to run) in eclipse (It is hard to know what order eclipse/junit will run the tests) - SecondTest FAILs - it is attempting to connect with the CXF client proxy.
Setup B
As setup A, but instead of first-test.xml having a CXF client proxy, it has a POJO of type TestObject
Scenario B1
Run FirstTest then SecondTest as a single execution in eclipse -PASS
Setup C
- JMockit 1.16
- The second-test.xml configuration has a TestObjectContainer bean containing an ITestObject that is actually a CXF proxy client for a web service.
Scenario C1
Run SecondTest on its own - FAIL (This passes on JMockit 1.6)
Setup D
- JMockit 1.16
- The second-test.xml configuration has a TestObjectContainer bean containing an ITestObject that has a POJO of type TestObject.
Scenario D1
Run SecondTest on its own - PASS
So, trying to summarise the factors involved:
- Using a CXF bean rather than a POJO causes failure (Scenarios A2 -> B1 and C1 -> D1)
- Running tests in isolation or as part of a set of tests causes failure (A1 -> A2)
- Using the latest JMockit can cause a failure (A1 -> D1)
Apologies for the length of post and amount of detail, but hopefully will aid diagnosis.
Many thanks,
Brian.
Files
src/main/java/com/example/ITestObject.java
package com.example;
import javax.jws.WebService;
@WebService
public interface ITestObject
{
public boolean isMocked();
}src/main/java/com/example/TestObject.java
package com.example;
import org.apache.log4j.Logger;
public class TestObject implements ITestObject
{
private static final Logger log = Logger.getLogger(TestObject.class);
public boolean isMocked()
{
log.info("In Real impl");
return false;
}
}src/main/java/com/example/TestObjectContainer.java
package com.example;
public class TestObjectContainer
{
private ITestObject testObject;
public ITestObject getTestObject()
{
return testObject;
}
public void setTestObject(ITestObject testObject)
{
this.testObject = testObject;
}
}src/test/java/com/example/FirstTest.java
package com.example;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class FirstTest
{
@Test
public void test1()
{
String configFileName = "/first-test.xml";
ClassPathXmlApplicationContext configContext = new ClassPathXmlApplicationContext(configFileName);
configContext.close();
}
}src/test/java/com/example/SecondTest.java
package com.example;
import mockit.Capturing;
import mockit.NonStrictExpectations;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SecondTest
{
@Capturing
ITestObject mockObject;
@Test
public void secondTest() throws Exception
{
new NonStrictExpectations()
{{
mockObject.isMocked(); result= true;
}};
String configFileName = "/second-test.xml";
ClassPathXmlApplicationContext configContext = new ClassPathXmlApplicationContext(configFileName);
Assert.assertTrue("Direct access to mock is not working",mockObject.isMocked());
TestObjectContainer springBeanObject = configContext.getBean("secondTestContainer",TestObjectContainer.class);
Assert.assertTrue("Spring bean access to mock is not working",springBeanObject.getTestObject().isMocked());
configContext.close();
}
}src/test/resources/first-test.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
">
<bean name="firstTestContainer" class="com.example.TestObjectContainer">
<property name="testObject" >
<!-- Choose either the jaxws bean, or the POJO bean -->
<jaxws:client
id="test-object-1"
serviceClass="com.example.ITestObject"
address="http://nohost1/path" />
<!-- <bean class="com.example.TestObject" /> -->
</property>
</bean>
</beans>src/test/resources/second-test.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
">
<bean name="secondTestContainer" class="com.example.TestObjectContainer">
<property name="testObject" >
<jaxws:client
id="test-object-2"
serviceClass="com.example.ITestObject"
address="http://nohost2/path" />
<!-- <bean class="com.example.TestObject" /> -->
</property>
</bean>
</beans>pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>repo</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Mocking issue repo</name>
<url />
<properties>
<spring.version>4.1.6.RELEASE</spring.version>
<cxf.version>3.0.4</cxf.version>
</properties>
<dependencies>
<dependency>
<groupId>com.googlecode.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.6</version>
<scope>test</scope>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.jmockit</groupId> -->
<!-- <artifactId>jmockit</artifactId> -->
<!-- <version>1.16</version> -->
<!-- <scope>test</scope> -->
<!-- </dependency> -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>