Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;
like image 358
Renaud is Not Bill Gates Avatar asked Mar 02 '23 22:03

Renaud is Not Bill Gates


1 Answers

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
like image 99
undetected Selenium Avatar answered Mar 05 '23 16:03

undetected Selenium