jbehave-junit-runner
jbehave-junit-runner copied to clipboard
jbehave-junit-runner requires causes Selenium WebDriver based tests to fail when Spring @Autowired
Another issue for the troubleshooting section.
JBehave Steps that make use Selenium WebDriver will fail because jbehave-junit-runner will cause the test to instantiate a WebDriver before it is required.
One workaround is to create a WebDriver Proxy/Wrapper that will delay the instantiation of the target Selenium WebDriver until it is really necessary.
For example:
public class WebDriverProxy implements WebDriver, JavascriptExecutor {
@SuppressWarnings("rawtypes")
private final Class webDriverClass;
private WebDriver driver;
@SuppressWarnings("rawtypes")
public WebDriverProxy(final Class webDriverClass) {
this.webDriverClass = webDriverClass;
}
public WebDriver getDriver() {
if (this.driver == null) {
try {
this.driver = (WebDriver) this.webDriverClass.newInstance();
}
catch (final InstantiationException e) {
e.printStackTrace();
}
catch (final IllegalAccessException e) {
e.printStackTrace();
}
}
return this.driver;
}
@PreDestroy
public void clean() {
quit();
}
public void get(final String url) {
getDriver().get(url);
}
public String getCurrentUrl() {
return getDriver().getCurrentUrl();
}
public String getTitle() {
return getDriver().getTitle();
}
public List<WebElement> findElements(final By by) {
return getDriver().findElements(by);
}
public WebElement findElement(final By by) {
return getDriver().findElement(by);
}
public String getPageSource() {
return getDriver().getPageSource();
}
public void close() {
getDriver().close();
}
public void quit() {
getDriver().quit();
}
public Set<String> getWindowHandles() {
return getDriver().getWindowHandles();
}
public String getWindowHandle() {
return getDriver().getWindowHandle();
}
public TargetLocator switchTo() {
return getDriver().switchTo();
}
public Navigation navigate() {
return getDriver().navigate();
}
public Options manage() {
return getDriver().manage();
}
public Object executeScript(final String script, final Object... args) {
return ((JavascriptExecutor) getDriver()).executeScript(script, args);
}
public Object executeAsyncScript(final String script, final Object... args) {
return ((JavascriptExecutor) getDriver()).executeAsyncScript(script, args);
}
}
and configure it in Spring:
<bean id="webDriver" class="com.foo.WebDriverProxy">
<constructor-arg value="org.openqa.selenium.firefox.FirefoxDriver"/>
</bean>
then use it in your JBehave Steps:
@Component("fooSteps")
public class FooSteps {
@Autowired
private WebDriver driver;
...
}