Reference to verifystatic on System class is failing after upgrading powermock version to 2X from 1X
Below are my current configurations
mockito-core - 2.27.0
powermock-api-mockito2 - 2.0.2
powermock-api-support - 2.0.2
powermock-module-junit4 - 2.0.2
Below code is working fine with powermock 1X
#RunWith(PowerMockRunner.class)
#PrepareForTest({ System.class })
public class SystemMockStaticTest {
#Test
public void testSystem() {
PowerMockito.mockStatic(System.class);
Properties properties = System.getProperties();
PowerMockito.verifyStatic();
System.getProperties();
}
}
I have made below changes to make it work with powermock2.0.2
PowerMockito.mockStatic(System.class);
Properties properties = System.getProperties();
PowerMockito.verifyStatic(System.class);
System.getProperties();
On running the test getting below exception.
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class java.lang.System
Mockito cannot mock/spy because :
- final class
at SystemMockStaticTest.testSystem(SystemMockStaticTest.java:19)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Please help on finding a fix for this exception.
Related
Source Code :
#Controller
public class HomeController {
private static final Logger log = LogManager.getLogger();
#GetMapping("/hello")
public #ResponseBody String getHello()
{
DemoClass cls = new DemoClass();
cls.helloworld();
log.info("INFO =====================");
return "Hello2";
}
}
The culprit in above code is "LogManager.getLogger()".
The above code is working perfectly fine on apache tomcat.
The stacktrace is as follows :
Java 11 is used.
Weblogic 14 is used.
log4j version : 2.19.0
Caused By: java.lang.UnsupportedOperationException: No class provided, and an appropriate one cannot be found.
at org.apache.logging.log4j.LogManager.callerClass(LogManager.java:573)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:598)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:585)
at com.example.demo.controller.HomeController.<clinit>(HomeController.java:12)
While porting a big JEE8 application to Java 17, I stumbled upon an IllegalAccessException when rendering a simple EL expression: #{myWarBean.defaultTZ.rawOffset}. I managed to reproduce the problem in a SSCCE on github. When you run the application on Wildfly application server (I'm using 26.1.1.Final), you get the following stacktrace:
SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-1) Error Rendering View[/index.xhtml]: javax.el.ELException: /index.xhtml #23,74 value="raw offset=#{myWarBean.defaultTZ.rawOffset}": java.lang.IllegalAccessException: class javax.el.BeanELResolver cannot access class sun.util.calendar.ZoneInfo (in module java.base) because module java.base does not export sun.util.calendar to unnamed module #6a1cb0de
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:77)
at javax.faces.api#3.1.0.SP01//javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.api#3.1.0.SP01//javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:181)
at javax.faces.api#3.1.0.SP01//javax.faces.component.UIOutput.getValue(UIOutput.java:140)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:198)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:328)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:143)
at javax.faces.api#3.1.0.SP01//javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:600)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:286)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:90)
at javax.faces.api#3.1.0.SP01//javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:571)
at javax.faces.api#3.1.0.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1648)
at javax.faces.api#3.1.0.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1651)
at javax.faces.api#3.1.0.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1651)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:461)
[...]
Caused by: javax.el.ELException: java.lang.IllegalAccessException: class javax.el.BeanELResolver cannot access class sun.util.calendar.ZoneInfo (in module java.base) because module java.base does not export sun.util.calendar to unnamed module #6a1cb0de
at javax.el.api#2.0.0.Final//javax.el.BeanELResolver.getValue(BeanELResolver.java:193)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:156)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:184)
at org.glassfish.jakarta.el#3.0.3.jbossorg-4//com.sun.el.parser.AstValue.getValue(AstValue.java:114)
at org.glassfish.jakarta.el#3.0.3.jbossorg-4//com.sun.el.parser.AstValue.getValue(AstValue.java:177)
at org.glassfish.jakarta.el#3.0.3.jbossorg-4//com.sun.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:39)
at org.glassfish.jakarta.el#3.0.3.jbossorg-4//com.sun.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:44)
at org.glassfish.jakarta.el#3.0.3.jbossorg-4//com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:183)
at org.jboss.weld.core#3.1.9.Final//org.jboss.weld.module.web.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at org.jboss.weld.core#3.1.9.Final//org.jboss.weld.module.web.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at com.sun.jsf-impl#2.3.17.SP01//com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:73)
... 73 more
Caused by: java.lang.IllegalAccessException: class javax.el.BeanELResolver cannot access class sun.util.calendar.ZoneInfo (in module java.base) because module java.base does not export sun.util.calendar to unnamed module #6a1cb0de
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)
at java.base/java.lang.reflect.Method.invoke(Method.java:560)
at javax.el.api#2.0.0.Final//javax.el.BeanELResolver.getValue(BeanELResolver.java:186)
... 83 more
It seems, the problem is the EL expression accessing a java.util.TimeZone. The TimeZone class uses sun.util.calendar.ZoneInfo internally. And it seems this is not legal any more.
This only happens with Java 17. When running in Java 11, this all works fine.
I can workaround the exception by adding the following arguments when starting wildfly:
--add-exports=java.base/sun.util.calendar=ALL-UNNAMED
However, I think it should be possible to run the example without this workaround.
Any ideas what I'm missing? Might this even be a bug in Java/JDK 17?
It's reproducible with a plain Java application class as follows:
package com.stackoverflow.q72361100;
import java.lang.reflect.Method;
import java.util.TimeZone;
public class Test {
public static void main(String... args) throws Exception {
TimeZone instance = TimeZone.getDefault();
Class<?> cls = instance.getClass();
Method method = cls.getMethod("getRawOffset");
Object result = method.invoke(instance); // java.lang.IllegalAccessException
System.out.println(result);
}
}
The issue here is that instance.getClass() returns sun.util.calendar.ZoneInfo as that's the implementation returned by TimeZone#getDefault(). The work around would be to use TimeZone.class instead of instance.getClass():
package com.stackoverflow.q72361100;
import java.lang.reflect.Method;
import java.util.TimeZone;
public class Test {
public static void main(String... args) throws Exception {
TimeZone instance = TimeZone.getDefault();
Class<?> cls = TimeZone.class; // Work around
Method method = cls.getMethod("getRawOffset");
Object result = method.invoke(instance);
System.out.println(result);
}
}
I'd argue that this will require a change in EL spec. Ideally it should search further in declared super classes if the method is accessible as per Method#canAccess() and then use it instead.
package com.stackoverflow.q72361100;
import java.lang.reflect.Method;
import java.util.TimeZone;
public class Test {
public static void main(String... args) throws Exception {
TimeZone instance = TimeZone.getDefault();
Class<?> cls = instance.getClass();
Method method = getAccessibleMethod(instance, cls, "getRawOffset"); // Look in superclasses as well.
Object result = method.invoke(instance);
System.out.println(result);
}
private static Method getAccessibleMethod(Object instance, Class<?> cls, String methodName) throws NoSuchMethodException {
Method method = cls.getMethod(methodName);
if (method.canAccess(instance)) {
return method;
}
return getAccessibleMethod(instance, cls.getSuperclass(), methodName);
}
}
I've created an issue at EL spec: https://github.com/jakartaee/expression-language/issues/188
Until they get it fixed, you can work around it by adding a dedicated getter for it:
public int getDefaultTZrawOffset() {
return getDefaultTZ().getRawOffset();
}
#{myWarBean.defaultTZrawOffset}
I'm working on a Quarkus Extension. But I have some problems to inject CDI Beans.
In the runtime module I have this class:
#ApplicationScoped
public class CustomRestClientBuilder{
//#Produces - Removed
//#ApplicationScoped - Removed
public RestClientBuilder newBuilder(String url) throws MalformedURLException {
return RestClientBuilder.newBuilder().baseUrl(new URL(url));
}
}
In the deployment module, I have this class:
class RestClientExtensionProcessor {
private static final String FEATURE = "rest-client-extension";
#BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}
#BuildStep
public AdditionalBeanBuildItem producer() {
return new AdditionalBeanBuildItem(CustomRestClientBuilder.class);
}
}
And the problem appears in testing classes. I put the Test in Deployment module and it fails (however, in runtime module it works).
public class CustomRestClientBuilderTest {
#Inject
private CustomRestClientBuilder customRest;
#RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
#Test
public void testGreeting() {
IDummyRestClient restClient = customRest.newBuilder("url")
.build(IDummyRestClient.class);
}
}
The error is:
Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception:
javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException:
Unsatisfied dependency for type CustomRestClientBuilder and qualifiers [#Default]
I've checked this post before:
Exposing CDI beans from Quarkus extensions
UPDATED
This way is working (adding the class I need for testing). Does it makes sense?
#RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(CustomRestClientBuilder.class,
IDummyRestClient.class));
I need to define a custom annotations in cucumber runner class. I have a event handler class where i get a callback when a test case is finished/started etc.
The issue i am facing is i am not able to get the runner class inside the event handler class, and hence i am unable to read the custom annotations applied in the runner class.
Is there a way for that in cucumber.
Eg. in junit , i can get the custom annotation applied in the test class as :
public void testFinished(Description description) { description.getTestClass();} from where i could read my annotation.
in testng, itestContext.getTestClass().getRealClass();.
Any help would be highly appreciated.
Many thanks in advance.
Eg. i need to read the annotations here,
private EventHandler<TestCaseFinished> caseFinishedEventHandler = new EventHandler<TestCaseFinished>() {
#Override
public void receive(TestCaseFinished event) {
//Read annotations here...
}
}; /*Or here*/ private EventHandler<TestRunFinished> runFinishedEventHandler = new EventHandler<TestRunFinished>() {
#Override
public void receive(TestRunFinished event) {
}
};
Solved this issue by :
For Junit : Extending Cucumber runner class. class argument of the constructor returns the runner class where custom annotations are present.
For TestNG : Extending AbstractTestNGCucumberTests in case of TestNG. this.getClass() returns the runner class where custom annotations are present.
I'm new on using ninject and Dependency Injection, and have a problem using it.
I try to using Ninject on my class libray, and building an integration tests.
now, I see in many example that, for using ninject is just specified the DI Module like this:
Public Class DIModule : NinjectModule
public override void Load()
{
Bind<IUSAServices>().To<USAServices>();
}
And then on my test class, I try to call my dependency is like this:
[TestClass]
public class USAIntegrationTests
{
private readonly IUSAServices _usaService;
public USAIntegrationTests(IUSAServices usaServices)
{
_usaService = usaServices;
}
[TestMethod]
public void ValidateUserTests()
{
Assert.IsTrue(_usaService.ValidateUser("username1", "password1"));
}
}
And Getting this error:
Unable to get default constructor for class USATests.IntegrationTests.USAIntegrationTests.
However I read the documentation and tried like this:
[TestClass]
public class USAIntegrationTests
{
private readonly IUSAServices _usaService;
public USAIntegrationTests()
{
using (IKernel kernel = new StandardKernel(new DIModule()))
{
_usaService = kernel.Get<IUSAServices>();
}
}
[TestMethod]
public void ValidateUserTests()
{
Assert.IsTrue(_usaService.ValidateUser("mantab", "banget"));
}
}
The test is works properly.
My question is, why I getting that error? is that some way to get around it?
Thanks in advance.
Unit test frameworks require your test classes to have a default constructor. You usually can't integrate DI containers with them. Instead of using constructor injection, you will have to call the container directly from your code, although for unit tests you should typically not have a container at all (for integration tests however, this is okay).
You can add a paramterless constructor for the class. It worked for me.