Repository navigation
OverrideWidget annotation does not work due to InstantiationException with error "SomeClass is abstract so it can't be instantiated" #392
Description
Description
Use a abstract widget class and two subclass to implement android and iOS widgets in Page Objects. But it would fail to init the PageObjects with exception: java.lang.IllegalArgumentException: java.lang.InstantiationException: com.foobar.uitest.widgets.TheAbastractCellWidget is abstract so it can't be instantiated
Environment
- java client build version or git revision if you use some shapshot: 1.8.0_77
- Appium server version or git revision if you use some shapshot: 1.5.2
- Desktop OS/version used to run Appium if necessary: n/a
- Node.js version (unless using Appium.app|exe) or Appium CLI or Appium.app|exe: 6.0
- Mobile platform/version under test: Android
- Real device or emulator/simulator: real
Details
@iOSFindBy(uiAutomator = ".tableViews()[0].cells()\")")
@AndroidFindBy(id ="com.foobar:id/main_content")
@OverrideWidget(androidUIAutomator = AndroidCellWidget.class,iOSUIAutomation = IOSCellWidget.class)
@WithTimeout(time = 30,unit = TimeUnit.SECONDS)
public List<TheAbastractCellWidget> cells;Scenario: TheAbastractCellWidget is the abstract Widget class, AndroidCellWidget is the Android implementation of it and IOSCellWidget is the iOS implementation.
This code is put in a page object class FooPage
I debugged the code, it seems that buildDefaultBy() method in class WidgetByBuilder started WhatIsNeeded.DEFAULT_OR_HTML type widget initialization before OverrideWidget mechanism and then it threw exeception.
Code To Reproduce Issue [ Good To Have ]
n/a
Ecxeption stacktraces
java.lang.IllegalArgumentException: java.lang.InstantiationException: com.foobar.uitest.widgets.MyChangbaPageFeedWorkCell is abstract so it can't be instantiated
at io.appium.java_client.pagefactory.OverrideWidgetReader.getConvenientClass(OverrideWidgetReader.java:64)
at io.appium.java_client.pagefactory.OverrideWidgetReader.getDefaultOrHTMLWidgetClass(OverrideWidgetReader.java:75)
at io.appium.java_client.pagefactory.WidgetByBuilder.getByFromDeclaredClass(WidgetByBuilder.java:67)
at io.appium.java_client.pagefactory.WidgetByBuilder.buildDefaultBy(WidgetByBuilder.java:98)
at io.appium.java_client.pagefactory.DefaultElementByBuilder.buildBy(DefaultElementByBuilder.java:185)
at io.appium.java_client.pagefactory.AppiumElementLocatorFactory.createLocator(AppiumElementLocatorFactory.java:57)
at io.appium.java_client.pagefactory.AppiumElementLocatorFactory.createLocator(AppiumElementLocatorFactory.java:44)
at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorateWidget(AppiumFieldDecorator.java:193)
at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorate(AppiumFieldDecorator.java:160)
at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:113)
at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:105)
at com.foobar.uitest.pages.FooPage.(BasePage.java:32)
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.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:514)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:215)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:589)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:820)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1128)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:782)
at org.testng.TestRunner.run(TestRunner.java:632)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
at org.testng.SuiteRunner.run(SuiteRunner.java:268)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
at org.testng.TestNG.run(TestNG.java:1064)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:74)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:121)
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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.InstantiationException: com.foobar.uitest.widgets.TheAbastractCellWidget is abstract so it can't be instantiated
at io.appium.java_client.pagefactory.OverrideWidgetReader.getConvenientClass(OverrideWidgetReader.java:65)
... 45 more
Link to Appium logs
no need
Activity
truebit commentedon May 19, 2016
According to this page-object doc section "what-if-interaction-with-a-widget-has-special-details-for-each-used-platform-but-the-same-at-high-level". It seems that it's the restriction of
OverrideWidgettruebit commentedon May 19, 2016
After I followed the instruction in section what-if-interaction-with-a-widget-has-special-details-for-each-used-platform-but-the-same-at-high-level":
I moved
iOSFindByandAndroidFindByannotations to the implementation class, the exception still exists. reopen.truebit commentedon May 19, 2016
I do not know the
WidgetBuilderdesign. According to my trace of the code execution flow,OverrideWidgetannotation element callsWidgetByBuilder's method to executebuildDefaultBy()first; which would got togetByFromDeclaredClass(WhatIsNeeded.DEFAULT_OR_HTML). This method would require the Wigdet class who must be not abstract.According to the document mentioned above, an abstract widget class should be the correct way to use
OverrideWidget. So I think this should be bug in the designtruebit commentedon May 20, 2016
After several trace, I think I know the root cause:
OverrideWidgetannotation must be specified withhtmlargument. My case only containsandroidUIAutomatorandiOSUIAutomation.If I assign
htmlwith any class in andorid or ios. it works...IMO,
OverrideWidgetshould support annotation withouthtmlassignmentTikhomirovSergey commentedon Jun 19, 2016
Yes. I was apble to reproduce that issue. I'm going to fix it ASAP.
Merge pull request #423 from TikhomirovSergey/#392