I have the following:
public class EnvWebEndpointExtensionEnvironmentPostProcessorTests {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Rule
public MockitoRule rule = MockitoJUnit.rule();
final EnvWebEndpointExtensionEnvironmentPostProcessor postProcessor = new EnvWebEndpointExtensionEnvironmentPostProcessor();
#Mock
ConfigurableEnvironment environmentMock;
#Mock
MutablePropertySources propertySourcesMock;
#Test
public void shouldAddPropertySource() {
final MutablePropertySources propertySources = new MutablePropertySources();
doReturn(propertySources) // line 40
.when(environmentMock).getPropertySources();
postProcessor.postProcessEnvironment(environmentMock, null);
assertNotNull(propertySources.get("actuators-defaults"));
}
#Test
public void shouldThrowExceptionOnFailingToAddLaptopPropertySource() {
thrown.expect(RuntimeException.class);
final MutablePropertySources propertySourcesReal = new MutablePropertySources();
doReturn(propertySourcesReal)
.when(environmentMock).getPropertySources();
doReturn(true)
.when(environmentMock).acceptsProfiles("laptop");
doReturn(propertySourcesMock)
.when(environmentMock).getPropertySources();
doThrow(IOException.class) // line 61
.when(propertySourcesMock).addBefore("actuators-defaults", any(ResourcePropertySource.class));
postProcessor.postProcessEnvironment(environmentMock, null);
}
}
When the tests are run individually, they pass but when they're both run, shouldAddPropertySource fails with:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.netflix.springboot.actuators.EnvWebEndpointExtensionEnvironmentPostProcessorTests.shouldThrowExceptionOnFailingToAddLaptopPropertySource(EnvWebEndpointExtensionEnvironmentPostProcessorTests.java:61)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
at com.netflix.springboot.actuators.EnvWebEndpointExtensionEnvironmentPostProcessorTests.shouldAddPropertySource(EnvWebEndpointExtensionEnvironmentPostProcessorTests.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.mockito.internal.junit.JUnitRule$1.evaluateSafely(JUnitRule.java:52)
at org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:43)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Considering the information I've found and the behavior above, Mockito is storing some static state but the level of my understanding isn't deep enough to figure out a fix for the above. What's the right fix and, in addition, the explanation for the fix?
If you use a matcher as an argument of a stubbed method call, all arguments must be matchers. So you need to replace "actuators-defaults" by eq("actuators-defaults").
I'm not sure why that throws that exception, though.
JB Nizet correctly diagnosed the root cause in his answer: When you use matchers for one argument, you have to use matchers for all arguments.
My hunch is that Mockito is correctly throwing InvalidUseOfMatchersException, which descends from RuntimeException, so your test erroneously passes without exercising your system-under-test. This is an important reason not to catch RuntimeException indiscriminately, especially at the top of a test method. This may also be a reason to use assertThrows or a try { methodUnderTest(); fail(); } catch (YourSpecificException expected) {} idiom.
If that's the case, you're seeing that specific exception because your test runner is calling your tests in shouldThrow, shouldAdd order in the same VM and Mockito keeps its matcher state in a static ThreadLocal that may survive between tests. If that theory is correct, then the InvalidUseOfMatchersException happens before Mockito can store the expectation from line 61, leaving the stubbing on line 61 technically unfinished. Because Mockito doesn't know when one test ends and another begins, it can't reset its state, so Mockito can only detect this case the next time you interact with Mockito (on line 40).
You could improve your experience by calling Mockito.validateMockitoUsage() in an #After method (or by using MockitoRule or MockitoJUnitRunner).
Related
I saw this error in our hazelcast cluster.
The code is trying to call executeOnKey() on an IMap. e.g.
IMap<MyKey, MyCachedClass> myMap = hz.getMap("my-map");
myMap.executeOnKey(myKey, new EntryProcessor() {
#Override
public Object process(Map.Entry entry) {
return entry.getValue().setItem(item);
}
#Override
public EntryBackupProcessor getBackupProcessor() {
return null;
}
});
...and am getting this exception:
Exception in thread "MYTHREAD" java.lang.LinkageError: loader (instance of com/hazelcast/internal/usercodedeployment/impl/ClassSource): attempted duplicate class definition for name: "com/mycompany/model/Item$ItemEnum"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.hazelcast.internal.usercodedeployment.impl.ClassSource.define(ClassSource.java:50)
at com.hazelcast.internal.usercodedeployment.impl.ClassLocator.tryToGetClassFromRemote(ClassLocator.java:163)
at com.hazelcast.internal.usercodedeployment.impl.ClassLocator.handleClassNotFoundException(ClassLocator.java:95)
at com.hazelcast.internal.usercodedeployment.impl.ClassSource.loadClass(ClassSource.java:65)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.hazelcast.internal.usercodedeployment.impl.ClassSource.define(ClassSource.java:50)
at com.hazelcast.internal.usercodedeployment.impl.ClassLocator.tryToGetClassFromRemote(ClassLocator.java:161)
at com.hazelcast.internal.usercodedeployment.impl.ClassLocator.handleClassNotFoundException(ClassLocator.java:95)
at com.hazelcast.internal.usercodedeployment.UserCodeDeploymentService.handleClassNotFoundException(UserCodeDeploymentService.java:89)
at com.hazelcast.internal.usercodedeployment.UserCodeDeploymentClassLoader.loadClass(UserCodeDeploymentClassLoader.java:57)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at com.hazelcast.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:288)
at com.hazelcast.nio.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:237)
at com.hazelcast.nio.IOUtil$ClassLoaderAwareObjectInputStream.resolveClass(IOUtil.java:646)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1868)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at java.util.ArrayList.readObject(ArrayList.java:797)
at sun.reflect.GeneratedMethodAccessor18.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1170)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2178)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:82)
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:75)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.readObject(AbstractSerializationService.java:269)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataInput.readObject(ByteArrayObjectDataInput.java:574)
at com.hazelcast.map.impl.operation.EntryOperation.readInternal(EntryOperation.java:263)
at com.hazelcast.spi.Operation.readData(Operation.java:728)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.readInternal(DataSerializableSerializer.java:160)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:106)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:51)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:187)
at com.hazelcast.spi.impl.NodeEngineImpl.toObject(NodeEngineImpl.java:323)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:398)
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:153)
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:123)
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:110)
at ------ submitted from ------.(Unknown Source)
at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolve(InvocationFuture.java:127)
at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolveAndThrowIfException(InvocationFuture.java:79)
at com.hazelcast.spi.impl.AbstractInvocationFuture.get(AbstractInvocationFuture.java:162)
at com.hazelcast.map.impl.proxy.MapProxySupport.executeOnKeyInternal(MapProxySupport.java:1099)
at com.hazelcast.map.impl.proxy.MapProxyImpl.executeOnKeyInternal(MapProxyImpl.java:109)
at com.hazelcast.map.impl.proxy.MapProxyImpl.executeOnKey(MapProxyImpl.java:757)
at com.mycompany.Processor.java
So to me this seemed like:
The 'executeOnKey(item)' command is being sent to the 'other' node in
the cluster where this data is located.
The other node is attempting to deserialize the 'item'.
The other node cannot find the class for the inner enum 'Item$ItemEnum'
The other node makes a request to UserCodeDeploymentService to fetch class definition.
Once the class definition is fetched, and it attempts to create the new class, a
LinkageError occurs.
I just cannot understand why it's getting a duplicate class exception, when it first claimed it couldn't find the class. And this error is proving difficult to replicate.
We do have 'userCodeDeployment' set to allow loading of remote class definitions. Our config looks like this:
UserCodeDeploymentConfig ucdConfig = new UserCodeDeploymentConfig();
ucdConfig.setEnabled(true);
ucdConfig.setClassCacheMode(UserCodeDeploymentConfig.ClassCacheMode.ETERNAL);
ucdConfig.setProviderMode(UserCodeDeploymentConfig.ProviderMode.LOCAL_AND_CACHED_CLASSES);
config.setUserCodeDeploymentConfig(ucdConfig);
So it sort of looks like it's doing what I'd expect. i.e. getting a remote class definition because it can't find it locally. Is just a puzzle as to why the exception is occurring.
Eventually worked this one out.
A simple example.
Assume two Hazelcast nodes. Both have userCodeDeployment switched on. (The ability to share class definitions over the wire.)
Node 1 has MyClass on it's classpath, Node 2 does not.
MyClass definition, note the inner enum (I think the inner enum can be swapped for an inner class and the same thing will happen).
public class MyClass implements Serializable {
private final InnerEnum enumVal;
public MyClass(InnerEnum enumVal) {
this.enumVal = enumVal;
}
public enum InnerEnum {
ONE, TWO, THREE;
}
}
From Node 1, the following code is run:
hz.getMap("myClassMap").put("myClassKey", new MyClass(MyClass.InnerEnum.ONE));
hz.getMap("myInnerEnumMap").put("myInnerEnumKey", MyClass.InnerEnum.TWO);
Then, on Node 2, the following code is run:
System.out.println(hz.getMap("myInnerEnumMap").get("myInnerEnumKey"));
System.out.println(hz.getMap("myClassMap").get("myClassKey"));
On Node 2, I see the following logged:
[TRACE] ClassLocator Loaded class com.mycompany.MyClass$InnerEnum from Member [myhost]:5701 - cc0b2872-7f5b-484b-a40f-7c7ba1fdc165
TWO
[TRACE] ClassLocator Loaded class com.mycompany.MyClass from Member [myhost]:5701 - cc0b2872-7f5b-484b-a40f-7c7ba1fdc165
Exception in thread "main" java.lang.LinkageError: loader (instance of com/hazelcast/internal/usercodedeployment/impl/ClassSource): attempted duplicate class definition for name: "com/mycompany/MyClass$InnerEnum"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.hazelcast.internal.usercodedeployment.impl.ClassSource.define(ClassSource.java:50)
at com.hazelcast.internal.usercodedeployment.impl.ClassLocator.tryToGetClassFromRemote(ClassLocator.java:163)
at com.hazelcast.internal.usercodedeployment.impl.ClassLocator.handleClassNotFoundException(ClassLocator.java:95)
at com.hazelcast.internal.usercodedeployment.UserCodeDeploymentService.handleClassNotFoundException(UserCodeDeploymentService.java:89)
at com.hazelcast.internal.usercodedeployment.UserCodeDeploymentClassLoader.loadClass(UserCodeDeploymentClassLoader.java:57)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at com.hazelcast.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:288)
at com.hazelcast.nio.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:237)
at com.hazelcast.nio.IOUtil$ClassLoaderAwareObjectInputStream.resolveClass(IOUtil.java:646)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1868)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:82)
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:75)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:187)
at com.hazelcast.map.impl.proxy.MapProxySupport.toObject(MapProxySupport.java:1245)
at com.hazelcast.map.impl.proxy.MapProxyImpl.get(MapProxyImpl.java:120)
at com.mycompany.main(Node2.java:74)
So:
Node 2 is first trying to fetch and display an instance of MyClass$InnerEnum. It fetches the InnerEnum class definition from Node 1 over hazelcast.
Node 2 then tries to fetch and display an instance of MyClass. It fetches the MyClass class definition from Node 1.
Hazelcast then loops through the inner classes of MyClass (which just contains InnerEnum) and asks the class loader to define them without checking whether they already exist.
See (from Hazelcast 3.11.1)
com.hazelcast.internal.usercodedeployment.impl.ClassLocator:160
Map<String, byte[]> innerClassDefinitions = classData.getInnerClassDefinitions();
classSource.define(name, classData.getMainClassDefinition());
for (Map.Entry<String, byte[]> entry : innerClassDefinitions.entrySet()) {
classSource.define(entry.getKey(), entry.getValue());
}
The easiest solution in our case was to pull InnerEnum out as a top level Enum.
Try creating the EntryProcessor as a static or a top level class and pass the item explicitly in its constructor. That hopefully should resolve the issue.
The JVM can get a little tricky with dynamic class loading, which is what is done by UserCodeDeployment.
Currently am writing Junit for our webservice code.
WebService Code and Junit code is written in the code section
When I run the Junit am getting the below error
java.lang.AbstractMethodError: javax.ws.rs.core.Response$ResponseBuilder.status(ILjava/lang/String;)Ljavax/ws/rs/core/Response$ResponseBuilder;
at javax.ws.rs.core.Response$ResponseBuilder.status(Response.java:921)
at javax.ws.rs.core.Response.status(Response.java:592)
at javax.ws.rs.core.Response.status(Response.java:603)
at javax.ws.rs.core.Response.ok(Response.java:638)
at javax.ws.rs.core.Response.ok(Response.java:650)
at com.renault.rntbci.stl.service.demande.impl.ListDemandServiceImpl.getDemandeListCount(ListDemandServiceImpl.java:281)
at com.renault.rntbci.stl.service.demande.impl.ListDemandeTest.testGetDemandeListCount(ListDemandeTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
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:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
One of my friend advised me to change the scope to test in pom.xml for jax rs version as below.
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<scope>test</scope>
<version>2.3.7.Final</version>
</dependency>
But still the same error is persisting. Kindly anyone please help me with a solution.
Thanks a lot in advance.
Note:
This is an existing application and I am new to this project which is with Java 1.7
public Response someMethod(String stringValue){
Map<String, Long> outputMap = new TreeMap<String, Long>();
try {
Long outputValue = service.getCount(stringValue);
//this call goes to a service and gets the db count for a table
outputMap.put("listCount", outputValue);
} catch (Exception e) {
logger.info(e.getMessage(), e);
}
return Response.ok(outputMap).build();
}
And Junit code is
#Mock
Service service;
#Mock
Response res;
#Test
public void testSomeMethod() throws SQLException {
String stringValue="12";
Long returnValue=10L;
when(service.getCount(stringValue)).thenReturn(returnValue);
res=obj.someMethod(stringValue);
Assert.assertNotNull(res);
}
I suspect that what's happening here is that you have two different versions of the JAR file containing the javax.ws.rs.core.Response$ResponseBuilder class. Between the two versions of this class that you have floating around, the abstract status() method changed. You need to go through your list of Maven dependencies by running the mvn dependency:tree command as per this answer. You need to identify the two different JAR versions containing the two different javax.ws.rs.core.Response$ResponseBuilder classes. Exclude the dependency version you don't want and keep the version you do want to keep.
It could be as simple as deleting the jboss-jaxrs-api_1.1_spec Jar file but depending on what other dependencies you have (and which transitive dependencies) there may be more to it than that.
Exception
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:42)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:105)
at us.ny.state.ij.safeact.ask.facade.AmmoSellerKeeperFacadeBeanTest.setUp(FacadeBeanTest.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
Code to mock
BusinessServiceFactory serviceFactory = BusinessServiceFactory.getInstance();
RegBusinessServiceImpl regCreateService =
serviceFactory.getRegBusinessService(adrEntityManager);
Test Code
#RunWith(PowerMockRunner.class)
#PrepareForTest({ BusinessServiceFactory.class})
public class FacadeBeanTest {
#Before
public void setUp() throws Exception {
AmmoSellerRegBusinessServiceImpl mockRegBusinessServiceImpl
= mock(AmmoSellerRegBusinessServiceImpl.class);
PowerMockito.doReturn(mockRegBusinessServiceImpl)
.when(BusinessServiceFactory.class,"getRegBusinessService",
(mockEntityManager)); //--- line 84 null pointer exception
}
}
I can't understand why I'm seeing the exception. I'd appreciate any suggestions.
FYI:
The solution is to use PowerMockito.mock() instead of Mockito.mock()
you should be doing
AmmoSellerRegBusinessServiceImpl mockRegBusinessServiceImpl
= PowerMockito.mock(AmmoSellerRegBusinessServiceImpl.class);
instead of
AmmoSellerRegBusinessServiceImpl mockRegBusinessServiceImpl
= mock(AmmoSellerRegBusinessServiceImpl.class);
// assuming your are using Mockito.mock()
// correct me if I am wrong
I also faced the same problem. This solution was the fix for me. Hope it helps.
You must use Mockito.when() for mocking methods that return a value. Also you need to use the PowerMockito.mockStatic() prior to mocking the methods of the static class.
PowerMockito.mockStatic(BusinessServiceFactory.class);
// use Mockito to set up your expectation
Mockito.when(BusinessServiceFactory.getInstance())
.thenReturn(mockRegBusinessServiceImpl);
Mockito.when(mockRegBusinessServiceImpl.getRegBusinessService())
.thenReturn(mockEntityManager);
Take a look at the PowerMock usage here to get a better understanding.
RunWith(PowerMockRunner.class)
#PrepareForTest(StaticCallInvoke.class)
#ContextConfiguration(locations = "file:test/spring/Beans.xml")
class TestClass extends Specification{
#Test
def "Testing staticMocking"() {
setup:
def someObject=new SomeObject();
someObject.someValue=100
PowerMockito.mockStatic(StaticCallInvoke.class)
when:
ClassUnderTest.executeSomething(someObject)
then:
someObject.someValue=110 /*Wrong Value,It says assertion failed. Thats absolutely fine becuase the value should be 100*/
}
}
When I try to change it to the correct value i.e 100, it throws this Exception,
java.lang.NullPointerException: Cannot invoke method leaveScope() on null object
at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:77)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
at com.cognizant.awcoe.gamification.rules.helper.executors.RuleExecTest.$spock_feature_0_0(RuleExecTest.groovy:54)
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.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
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:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) )
If I change it back to 100, it's all good again(But the assertion fails)
Above test is run using PowerMock 1.5,Spock-0.6 for groovy 1.8.
Not sure what's happening here.
Any help is much appreciated :)
Looks like PowerMock is installing its own JUnit runner, overriding Spock's one. In other words, Spock is no longer in charge of executing this test, and PowerMock obviously can't execute it correctly. Perhaps PowerMock doesn't support custom JUnit runners, in which case it won't work with Spock.
Spock and PowerMock work together nicely if done right, see my repo https://github.com/kriegaex/Spock_PowerMock. You need to do something like
#PrepareForTest([StaticCallInvoke.class])
#ContextConfiguration(locations = "file:test/spring/Beans.xml")
class TestClass extends Specification {
#Rule PowerMockRule rule = new PowerMockRule();
def "Testing staticMocking"() {
// ...
}
}
Im getting a cast exception thrown at the line "handDetailList.each". I don't understand why my code is trying to cast a list to a "Hand" class? It seems to me that sometimes Groovy does strange things with casting....?
private Hand buildHands(List handDetailList) {
def parsedHand = new Hand()
parsedHand.setTableName(handDetailList.get(1))
handDetailList.each {
}
}
I get the following exception (I have edited the exception, line 70 is "handDetailList.each {"):
Exception in thread "main" org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object <details of the list, omitted> with class 'java.util.ArrayList' to class 'gameMechanics.Hand' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: gameMechanics.Hand(java.lang.String,........
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:358)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:599)
at advisor.HistoryParser.buildHands(HistoryParser.groovy:70)
at advisor.HistoryParser.this$2$buildHands(HistoryParser.groovy)
at advisor.HistoryParser$this$2$buildHands.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at advisor.HistoryParser.parse(HistoryParser.groovy:57)
at advisor.HistoryParser$parse.call(Unknown Source)
each returns the list that each was called on.
You have said the function returns an object of type Hand, and as Groovy automatically returns the last statement in a method, it is trying to convert the list to an instance of Hand and failing...
What is it you want to return? The parsedHand variable?
Maybe try:
private Hand buildHands(List handDetailList) {
def parsedHand = new Hand()
parsedHand.setTableName(handDetailList.get(1))
handDetailList.each {
}
parsedHand
}
if so.