Мы создаем REST API с помощью тестов. API работает отлично, и у нас нет никаких проблем с ним. Ошибки, которые мы получаем, находятся в тестовой части.
В тестах используется библиотека Rest Assured. Мы должны использовать JDK 17 в качестве выбора уровня организации.
Мы столкнулись с проблемой при выполнении наших тестов REST Assured после обновления до JDK 17. Возможно, это как-то связано с тем, что отражение не разрешено в JDK 17.
Мы получаем java.lang.ExceptionInInitializerError для следующих строк кода
RestAssured.baseURI = Constants.BASE_URI;
RestAssured.port = Constants.PORT;
RestAssured.basePath = Constants.BASE_PATH;
Есть ли у вас какие-либо советы/решения/обходные пути. Мы не можем использовать другую версию Java, поскольку это выбор на уровне организации.
Мы устанавливаем baseURI, порт и basePath для всех тестов, используя приведенный выше код. Раньше это работало, но после того, как мы перешли на JDK 17, похоже, возникла проблема.
java.lang.ExceptionInInitializerError
at io.restassured.builder.RequestSpecBuilder.<init>(RequestSpecBuilder.java:79)
at com.teamcenter.services.strong.utils.TestBase.createRequestSpecification(TestBase.java:99)
at com.teamcenter.services.strong.utils.TestBase.createRequestSpecification(TestBase.java:82)
at com.teamcenter.services.strong.utils.TestBase.setUp(TestBase.java:116)
at com.teamcenter.services.strong.IncludeRuleTest.setUp(IncludeRuleTest.java:36)
at junit.framework.TestCase.runBare(TestCase.java:140)
at junit.framework.TestResult$1.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:130)
at junit.framework.TestSuite.runTest(TestSuite.java:241)
at junit.framework.TestSuite.run(TestSuite.java:236)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make java.lang.String(char[],int,int,java.lang.Void) accessible: module java.base does not "opens java.lang" to unnamed module @3cda1055
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.Constructor.checkCanSetAccessible(Constructor.java:188)
at java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:181)
at org.codehaus.groovy.reflection.CachedConstructor$1.run(CachedConstructor.java:44)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at org.codehaus.groovy.reflection.CachedConstructor.<init>(CachedConstructor.java:42)
at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:79)
at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:69)
at org.codehaus.groovy.util.LazyReference.getLocked(LazyReference.java:49)
at org.codehaus.groovy.util.LazyReference.get(LazyReference.java:36)
at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:268)
at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)
at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:253)
at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:285)
at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:295)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:261)
at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:873)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createPojoSite(CallSiteArray.java:125)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:166)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at io.restassured.internal.RequestSpecificationImpl.<clinit>(RequestSpecificationImpl.groovy:86)
... 19 more
Некоторое объяснение ошибки см. в разделе Как решить InaccessibleObjectException («Невозможно сделать {member} доступным: модуль {A} не «открывает {package}» для {B}») в Java 9?.
@ElliottFrisch Это говорит о разделенных пакетах. Ошибка OP не связана с разделенными пакетами. Или я что-то упускаю?
@Slaw Мы понятия не имеем, как OP упаковывает свой код или даже какую версию проверенного OP использует; отсюда и догадки. Но модуль java.base не «открывает java.lang» для безымянного модуля, подразумевающего модули. Модули Java 9+. И эта заметка помечена как «java 9+».
Это фундаментальная проблема Groovy.
Groovy — это динамический язык, использующий Reflection для доступа к элементам и вызывающий setAccessible(true) для всех из них.
Это не должно было работать таким образом, но было реализовано таким образом, чтобы исправить доступ из закрытий к закрытым членам с побочным ущербом от игнорирования private везде. Видеть
Приватный метод в groovy не является приватным
Классный вызов приватного метода в суперклассе Java
Конструктор String(char[],int,int,java.lang.Void) даже не существует в более старых версиях Java, поэтому это не тот случай, когда старая программа полагается на него, а вместо этого среда выполнения Groovy пытается кэшировать все члены класса и вызывает setAccessible(true) заранее, как мы можем вывести из трассировки стека
at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:268)
at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)
Обратите внимание на часть имени MetaClass, предлагающую обработку для каждого класса, и множественное число в имени метода getConstructors, предполагающее, что он пытается получить все конструкторы.
Поскольку вы даже не пытаетесь получить доступ к члену класса String в опубликованном коде, кажется, что уже достаточно использовать/сослаться на тип, чтобы вызвать инициализацию метаинформации.
Для обычного программного обеспечения Java мы бы предложили определить места, где программное обеспечение обращается к внутренним компонентам, а затем включить конкретную опцию --add-opens в качестве временного обходного пути и переписать конкретную часть, чтобы не получать доступ к внутренним компонентам в долгосрочной перспективе.
Однако для Groovy вам придется добавить такую опцию для каждого пакета, который использует сценарий, без возможности переписать код, чтобы в конечном итоге избавиться от проблемы.
Что не означает, что не может быть действительно проблемных частей, получающих доступ к внутренностям, возможно, случайно. Просто вы не можете отличить их от законного использования классов.
Маловероятно, что поведение, продолжающееся с 2007 года, будет исправлено или что такое исправление может быть сделано без нарушения чего-либо в других местах, то есть непреднамеренных обращений, упомянутых выше, или даже преднамеренных, поскольку некоторые люди считают это особенностью.
Спасибо. Для тех, кто посетит эту ветку в будущем, я работал со старыми версиями Groovy и Rest-Assured. Проблема решена после обновления до надежной версии 5.3.0, заводной версии 4.0.9. Очень ценю услуги сообщества stackoverflow.
Я люблю гадать.