java.lang.NoSuchMethodError: org.openqa.selenium.support.ui.Wait.until(Lcom/google/common/base/Function;) using selenium-server-standalone-3.12.0

蓝咒 提交于 2020-06-23 07:03:31

问题


I've been struggling with selenium to fix this issue:

java.lang.NoSuchMethodError: org.openqa.selenium.support.ui.Wait.until(Lcom/google/common/base/Function;)Ljava/lang/Object;

This is where I get this error:

Wait<WebDriver> wait = new FluentWait<>(getDriverInstance())
        .withTimeout(timeout, TimeUnit.SECONDS)
        .pollingEvery(frequency, TimeUnit.SECONDS)
        .ignoring(NoSuchElementException.class);
wait.until(driver -> {
    assert driver != null;
    elt.click();
    return true;
});

The most solutions on the internet suggest to use Guava 21, but this is not working for me.

Running selenium locally works just fine, and I don't get this issue, the problem is we use a runner that will use the selenium-server-standalone-3.12.0 to run tests on multiple virtual machines, and in the classpath we define all the dependencies we use, where I declared Guava as well, I also tried other versions of Guava from 19 to 23.

I tried multiple solutions and now I'm out of ideas, I don't know why I'm still getting this error even though I have declared Guava, and I can clearly see when I run tests locally, that Guava 23 works just fine.

I'm using java 1.8_71.

When I checked the code source of selenium-server-standalone-3.12.0 the Wait interface looks like this:

import java.util.function.Function;

public interface Wait<F> {
    <T> T until(Function<? super F, T> var1);
}

But in local it looks like this:

import com.google.common.base.Function;

public interface Wait<F> {
    <T> T until(Function<? super F, T> var1);
}

But since com.google.common.base.Function is extending com.google.common.base.Function in Guava 23, this shouldn't be a problem, so why I'm still getting this error ?

Thanks in advance.

Update:

I have checked the content of the standalone jar, and it contains Guava version 23.6-jre, so I'm highly skeptical about the issue being from guava.

I also checked the Wait interface and it's defined like this:

import java.util.function.Function;

public interface Wait<F> {
    <T> T until(Function<? super F, T> var1);
}

I still don't understand why I'm getting until(Lcom/google/common/base/Function;) in the exception when the used Function interface is from java.util.function and not com.google.common.base

Update 2

I have somehow solved this issue by looking at how intellij executes my jar, so I added D:\..\target\test-classes to the classpath and the exception disappeared for some reason, why this happened ? and how can I include the files in test-classes to my final jar ?

Normally I have a bat file that runs my test:

@SETLOCAL
@ECHO OFF
@set JAVA_HOME="C:\Program Files\Java\jdk1.8.0_231"
@set PATH=%JAVA_HOME%\bin;D:\drivers;%PATH%


@set CLASSPATH=.;
@set CLASSPATH=%CLASSPATH%D:\sln\lib\*;
@set CLASSPATH=%CLASSPATH%D:\sln\selenium-server-standalone-3.12.0.jar;

echo %CLASSPATH%
"C:\Program Files\Java\jdk1.8.0_231\bin\java.exe" com.sln.Runner %*

which I use as following:

D:\sln\Run.bat -u localhost -f D:\sln\target\sln-1.0-SNAPSHOT-tests.jar -c com.sln.SeleniumTest ...

This won't work I'll get the NoSuchMethodError exception unless I add this to the class path:

@set CLASSPATH=%CLASSPATH%D:\sln\target\test-classes;

回答1:


This error message...

java.lang.NoSuchMethodError: org.openqa.selenium.support.ui.Wait.until(Lcom/google/common/base/Function;)Ljava/lang/Object;

...implies that the Guava version was incompatible.


As you are using selenium-server-standalone-3.12.0 as per the contents of selenium-java-3.12.0 client kits the supported guava version is:

guava-23.6-jre


Snapshot

guava


Solution

An immediate solution would be to:

  • Upgrade Guava with guava-23.6-jre.jar

The real issue

In your first update as you have confirmed that Guava version is 23.6-jre, the real issue seems to be constructor of FluentWait. The argument type for withTimeout and pollingEvery post Selenium v3.11.0, which was:

  • pollingEvery: pollingEvery(long duration, java.util.concurrent.TimeUnit unit)
  • withTimeout: withTimeout(long duration, java.util.concurrent.TimeUnit unit)

Are now Deprecated and the new type is java.time.Duration. So your effective code block will be:

Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofMillis(500))
.ignoring(NoSuchElementException.class);

You can find a detailed discussion in The type FluentWait is not generic; it cannot be parameterized with arguments error for FluentWait Class through Selenium and Java


Additional Consideration

Additionally,

  • Your JDK version is 1.8_71 which is pretty old and ancient.
  • Solution: Ensure that JDK is upgraded to current levels JDK 8u222.

Best Practices

As per the best practices you need to:

  • Upgrade JDK to recent levels JDK 8u222.
  • Upgrade Selenium to current levels Version 3.141.59.
  • GeckoDriver and Firefox specific:
    • Upgrade GeckoDriver to GeckoDriver v0.26.0 level.
    • GeckoDriver is present in the desired location.
    • GeckoDriver is having executable permission for non-root users.
    • Upgrade Firefox version to Firefox v72.0 levels.
  • ChromeDriver and Chrome specific:
    • ChromeDriver is updated to current ChromeDriver v79.0.3945.36 level.
    • Chrome is updated to current Chrome Version 79.0 level. (as per ChromeDriver v79.0 release notes)
  • Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
  • (WindowsOS only) Use CCleaner tool to wipe off all the OS chores before and after the execution of your Test Suite.
  • (LinuxOS only) Free Up and Release the Unused/Cached Memory in Ubuntu/Linux Mint before and after the execution of your Test Suite.
  • If your base Web Client version is too old, then uninstall it through Revo Uninstaller and install a recent GA and released version of Web Client.
  • Take a System Reboot.
  • Execute your Test as a non-root user.
  • Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.

Reference

You can find a relevant detailed discussion in:

  • org.openqa.selenium.remote.service.DriverService$Builder.createArgs()Lcom/google/common/collect/ImmutableList; with Selenium 3.5.3 Chrome 76



回答2:


This is compatibility issue. To solve it, you can use Guava version 21 + selenium version 3.2.0 + JDK 8.

For more details you can check below link:

https://softwaretestingboard.com/q2a/1907/function-webdriver-fluentwait-webdriver-applicable-arguments#axzz68BFzmEjv

I hope it will help you.




回答3:


Simple short answer: You have dependency issues with an outdated guava version!

-> Do this: In every single project explicitly exclude the guava dependency from every single dependency that requests it (use the dependency graph to find these) or better exclude it in the parent (if you have one)

-> Then add the guava 23.0 (or newer) dependency explicitly.

This will fix it. Right now from somewhere an old guava version is being pulled that doesnt have the "until" method (or at least not with this parameter).

Good Luck! :)




回答4:


I think you should check under D:\sln\ and D:\sln\lib\ if there's any other version of selenium library in there. Delete it out if there's one.

From the error message, it seems like when you execute the batch script it use a different version of Selenium from a different selenium jar file. Probably the old version of selenium jar that haven't had the Wait.until method yet.



来源:https://stackoverflow.com/questions/59732541/java-lang-nosuchmethoderror-org-openqa-selenium-support-ui-wait-untillcom-goog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!