Skip to content
Advertisement

java.lang.ExceptionInInitializerError with AppiumFieldDecorator – JAVA, Cucumber, Appium

Hey all!
I’m trying to set up an automation project using Cucumber & Appium for Mobile apps (iOS and Android both).
I plan to write the project in JAVA and I use Gradle for implementing the desired dependencies.

So I wrote a small project and for some reason it keeps failing with the following error:

java.lang.ExceptionInInitializerError

The exception occurs when I’m calling PageFactory.initElements(new AppiumFieldDecorator(driver), this);

This is how I implemented the page object class:

public class OnboardingPageObjects {

    public OnboardingPageObjects(AppiumDriver driver) {
        PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }

    @AndroidFindBy(id = "com.bupp.wood_spoon_chef.staging:id/orangeBtnBackground")
    public WebElement getStartedButton;
}

This is the tests class where it fails within the @Before hook:

public class FeedSteps {

    public Capabilities cap;
    public OnboardingPageObjects onboardingPageObjects;

    @Before()
    public void setup() throws MalformedURLException {
        cap = new Capabilities();
        cap.preparation("4723", Platform.ANDROID);
        onboardingPageObjects = new OnboardingPageObjects(cap.getDriver());
    }
    ...
}

This is the class where I initialize the AppiumDriver (currently only AndroidDriver, iOS driver is not in use):

public class Capabilities {

    private AppiumDriver driver = null;
    public DesiredCapabilities capabilities = new DesiredCapabilities();

    public void preparation(String port, Platform platform) throws MalformedURLException {
        if (platform == Platform.IOS) {
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
            //capabilities.setCapability(MobileCapabilityType.UDID, "emulator-5554");
            capabilities.setCapability(IOSMobileCapabilityType.BUNDLE_ID, "");
            capabilities.setCapability("instrumentedApp", true);
            driver = new IOSDriver(new URL("http://localhost:"+port+"/wd/hub"), capabilities);
            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        } else {
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
            capabilities.setCapability(MobileCapabilityType.UDID, "emulator-5554");
            capabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.bupp.wood_spoon_chef.staging");
            capabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "com.bupp.wood_spoon_chef.presentation.features.splash.SplashActivity");
            driver = new AndroidDriver(new URL("http://localhost:"+port+"/wd/hub"), capabilities);
            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        }
    }

    public AppiumDriver getDriver() {
        return driver;
    }

    public void stopDriver() {
        driver.quit();
    }
}

The same code works if I change:

  1. The new AppiumFieldDecorator(driver) and instead doing this:PageFactory.initElements(driver, this);
  2. Change @AndroidFindBy to @FindBy

This is the error I get:

Step failed
java.lang.ExceptionInInitializerError
    at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:53)
    at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:33)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.proxyForAnElement(AppiumFieldDecorator.java:209)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.access$000(AppiumFieldDecorator.java:61)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator$1.proxyForLocator(AppiumFieldDecorator.java:100)
    at org.openqa.selenium.support.pagefactory.DefaultFieldDecorator.decorate(DefaultFieldDecorator.java:63)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorate(AppiumFieldDecorator.java:147)
    at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:111)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:103)
    at com.eatwoodspoon.homechefs.pages.onboarding.OnboardingPageObjects.<init>(OnboardingPageObjects.java:12)
    at com.eatwoodspoon.homechefs.stepsdefs.feed.FeedSteps.setup(FeedSteps.java:22)
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @6073f712
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:464)
    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:339)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:96)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:94)
    at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
    at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:119)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:294)
    at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)
    at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:174)
    at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:153)
    at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)
    at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:53)
    at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:33)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.proxyForAnElement(AppiumFieldDecorator.java:209)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.access$000(AppiumFieldDecorator.java:61)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator$1.proxyForLocator(AppiumFieldDecorator.java:100)
    at org.openqa.selenium.support.pagefactory.DefaultFieldDecorator.decorate(DefaultFieldDecorator.java:63)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorate(AppiumFieldDecorator.java:147)
    at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:111)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:103)
    at com.eatwoodspoon.homechefs.pages.onboarding.OnboardingPageObjects.<init>(OnboardingPageObjects.java:12)
    at com.eatwoodspoon.homechefs.stepsdefs.feed.FeedSteps.setup(FeedSteps.java:22)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at io.cucumber.java.Invoker.doInvoke(Invoker.java:66)
    at io.cucumber.java.Invoker.invoke(Invoker.java:24)
    at io.cucumber.java.AbstractGlueDefinition.invokeMethod(AbstractGlueDefinition.java:47)
    at io.cucumber.java.JavaHookDefinition.execute(JavaHookDefinition.java:64)
    at io.cucumber.core.runner.CoreHookDefinition.execute(CoreHookDefinition.java:46)
    at io.cucumber.core.runner.HookDefinitionMatch.runStep(HookDefinitionMatch.java:21)
    at io.cucumber.core.runner.ExecutionMode$1.execute(ExecutionMode.java:10)
    at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:85)
    at io.cucumber.core.runner.TestStep.run(TestStep.java:57)
    at io.cucumber.core.runner.TestCase.run(TestCase.java:78)
    at io.cucumber.core.runner.Runner.runPickle(Runner.java:75)
    at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:128)
    at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$5(CucumberExecutionContext.java:129)
    at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
    at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:129)
    at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:128)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:249)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)
    at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:110)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:200)
    at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
    at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
    at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:111)
    at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:82)
    at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
    at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
    at io.cucumber.core.cli.Main.run(Main.java:87)
    at io.cucumber.core.cli.Main.main(Main.java:30)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @6073f712
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
    at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
    at net.sf.cglib.core.ReflectUtils$1.run(ReflectUtils.java:61)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:569)
    at net.sf.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:52)
    at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243)
    at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:332)
    ... 64 more

This is the Gradle build dependencies:

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
    implementation 'io.appium:java-client:8.0.0'
    implementation 'org.seleniumhq.selenium:selenium-java:4.1.4'
    testImplementation group: 'org.testng', name: 'testng', version: '7.6.0'
    implementation 'io.cucumber:cucumber-java:7.3.3'
    implementation group: 'io.cucumber', name: 'cucumber-testng', version: '7.3.4'
}

Please help, I don’t know what to do!

Advertisement

Answer

OK, so I found the problem and a solution!


The problem was with the runner configuration.
For some reason if we initialize the page objects inside the @Before hook of Cucumber it fails but if we do the same within the @BeforeClass hook of TestNG or @Before hook of JUnit it worked flawlessly!

The solution:
I changed the configuration of the runner.
Instead of running the feature file directly, I used @CucumberOptions within a TestRunner class. Here is my TestRunner class followed by this article: https://www.lambdatest.com/support/docs/running-cucumber-scripts-with-testng-and-selenium/

package com.eatwoodspoon.homechefs.infra;

import com.eatwoodspoon.homechefs.infra.setups.DriverCapabilities;
import io.cucumber.testng.CucumberOptions;
import io.cucumber.testng.FeatureWrapper;
import io.cucumber.testng.PickleWrapper;
import io.cucumber.testng.TestNGCucumberRunner;
import org.testng.annotations.*;

import java.net.MalformedURLException;

@CucumberOptions(features = {"src/test/resources/features"},
        glue = {"com/eatwoodspoon/homechefs/stepsDefinitios"},
        plugin = {
        "pretty",
        "html:target/cucumber-reports/cucumber-pretty",
        "json:target/cucumber-reports/CucumberTestReport.json",
        "rerun:target/cucumber-reports/rerun.txt",
        "json:target/cucumber-reports/CucumberTestReport.json"
        }
)
public class TestRunner {

    private TestNGCucumberRunner testNGCucumberRunner;

    public DriverCapabilities cap;
    public static HomeChefApp homeChefApp;

    @BeforeClass(alwaysRun = true)
    public void setUpCucumber() {
        testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
    }

    @BeforeMethod(alwaysRun = true)
    public void setUpClass() throws MalformedURLException {
        cap = new DriverCapabilities();
        cap.preparation("4723", Platform.ANDROID);
        homeChefApp = new HomeChefApp(cap.getDriver());
    }

    @Test(groups = "cucumber", description = "Runs Cucumber Feature", dataProvider = "features")
    public void feature(PickleWrapper pickle, FeatureWrapper cucumberFeature) {
        testNGCucumberRunner.runScenario(pickle.getPickle());
    }

    @DataProvider
    public Object[][] features() {
        return testNGCucumberRunner.provideScenarios();
    }

    @AfterClass(alwaysRun = true)
    public void tearDownClass() {
        testNGCucumberRunner.finish();
        cap.stopDriver();
    }
}
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement