I have a simple jsf app with one Bean.
import org.omnifaces.cdi.ViewScoped;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import java.io.Serializable;
#Named
#ViewScoped
public class IndexMg implements Serializable {
List list;
#PostConstruct
public void init() {
list = new ArrayList();
list.add("as");
list.add("dsu");
}
#PreDestroy()
public void end() {
System.out.println("predestroy called");
}
}
according to this answer and conversation down this post and also OmniFaces documentation OmniFaces ViewScoped bean should invoke #PreDestroy function when I navigate away by GET, or close the browser tab/window but nothings happens until session destroy.
I'm using Wildfly 15 as Application Server and i can see activeViewMaps in sessions. Yoy can see sessions content here .
It's something like this :
com.sun.faces.application.view.activeViewMaps {1d31c745-c202-4256-a2c6-60035bfdd8e7={org.omnifaces.cdi.viewscope.ViewScopeStorageInSession=b557d2aa-ba35-4ff2-9f4e-3cc4ac312c9a}, ca02df9d-be65-4a75-a399-3df9eabbcfd3={org.omnifaces.cdi.viewscope.ViewScopeStorageInSession=aaef6a5a-d385-4e33-a990-200f94b67583}}
I opened multiple windows an closed them but non of them destroyed until session destroy(30 minutes later). What's wrong? did i forget anything?
this is my pom
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.3.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.omnifaces/omnifaces -->
<dependency>
<groupId>org.omnifaces</groupId>
<artifactId>omnifaces</artifactId>
<version>3.2</version>
</dependency>
</dependencies>
Related
I wanted to run my cucumber features with TestNG for parallel execution. I continue to keep on running into the issue where testNG fails to find the matching glue code. Although the code is written and mapped correctly with Steps.
Test Execution is skipped and error states that There were undefined steps that needs to be defined.
I then moved the Step Definitions class into the same package where my Test Runner class was, and the execution went on successfully.
I fail to understand that why testNG is not able to recognize the glue code in different package. I tried to work on different dependencies as well but that didn't worked as well. Is there any other way to make sure testNG looks at the right place for step definitions ?
Below is the POM :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>CucumberPractice</groupId>
<artifactId>CucumberPractice</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>CucumberPractice</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-core</artifactId>
<version>4.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>4.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>4.7.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-jvm-deps -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-jvm-deps</artifactId>
<version>1.0.6</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-core -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/gherkin -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>gherkin</artifactId>
<version>5.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-html -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-html</artifactId>
<version>0.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-testng -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>4.7.2</version>
</dependency>
</dependencies>
</project>
Below is the Step Definition class :
package CucumberPageLogic;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import junit.framework.Assert;
public class PageLogic {
public WebDriver driver;
public WebDriverWait wait;
#Before("#Chrome")
public void driverSetup() {
System.out.println("In Before");
System.setProperty("webdriver.chrome.driver", "driverPath");
driver= new ChromeDriver();
wait= new WebDriverWait(driver,20);
}
#After
public void tearDown() {
driver.quit();
}
#Given("User opens Salesforce.com")
public void userOpensSalesforceCom() {
driver.get("https://www.salesforce.com/in/?ir=1");
driver.manage().window().maximize();
}
#Given("Home Page is sucessfully loaded")
public void homePageIsSucessfullyLoaded() {
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[#class='btn-container hidden-xs']//span[contains(text(),'Try')]")));
}
#When("User clicks on Try For Free button")
public void userClicksOnTryForFreeButton() {
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[#class='btn-container hidden-xs']//span[contains(text(),'Try')]"))).click();
}
#When("^User enters SignUp \"(.*)\" \"(.*)\" \"(.*)\" information$")
public void userEntersSignUpInformation(String firstname, String lastname, String jobtitle) {
driver.findElement(By.name("UserFirstName")).sendKeys(firstname);
driver.findElement(By.name("UserLastName")).sendKeys(lastname);
Select select = new Select(driver.findElement(By.name("UserTitle")));
select.selectByVisibleText(jobtitle);
}
#Then("New Tab is opened")
public void newTabIsOpened() {
Set<String> handles = driver.getWindowHandles();
if(handles.isEmpty()) {
Assert.fail();
}
System.out.println("these are the handles :"+handles);
System.out.println("Current Handle :"+driver.getWindowHandle());
for(String handle:handles) {
if(!handle.equals(driver.getWindowHandle())) {
System.out.println("Switching to "+handle);
driver.switchTo().window(handle);
break;
}
}
}
#Then("User goes back to home page")
public void userGoesBackToHomeTab() {
Set<String> handles = driver.getWindowHandles();
if(handles.isEmpty()) {
Assert.fail();
}
System.out.println("these are the handles :"+handles);
System.out.println("Current Handle :"+driver.getWindowHandle());
for(String handle:handles) {
if(!handle.equals(driver.getWindowHandle())) {
System.out.println("Switching to "+handle);
driver.switchTo().window(handle);
break;
}
}
}
#Then("Sign up form is visible")
public void signUpFormIsVisible() {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.name("UserFirstName")));
}
#Then("validate home page content")
public void validateHomePageContent() {
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[#class='btn-container hidden-xs']//span[contains(text(),'Try')]")));
}
}
Below is the Test Runner Class :
package CucumberPractice;
import org.testng.annotations.DataProvider;
import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.CucumberOptions.SnippetType;
import io.cucumber.testng.AbstractTestNGCucumberTests;
//#RunWith(Cucumber.class)
#CucumberOptions(features= {"C:\\Users\\komehta\\eclipse-workspace\\CucumberPractice\\src\\test\\java\\CucumberPractice"},
dryRun=false,
glue= {"CucumberPageLogic"},
snippets= SnippetType.CAMELCASE,
tags= {"#NewTabFeature"},
strict=false,
plugin= {
"pretty","html:test-outout",
"json:json_output/cucumber.json",
"junit:junit_xml/cucumber.xml"
})
public class CucumberTestRunner extends AbstractTestNGCucumberTests {
#Override
#DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
}
Feature File :
#NewTabFeature #Chrome
Feature: Opening the WebPage in New Tab
#NewTabSnr1
Scenario: Open the link in a New WebPage and Validate the Content
Given User opens Salesforce.com
And Home Page is sucessfully loaded
When User clicks on Try For Free button
Then New Tab is opened
And Sign up form is visible
#NewTabSnr2
Scenario Outline: Validate the Content on HomePage after entering details on new tab
Given User opens Salesforce.com
And Home Page is sucessfully loaded
When User clicks on Try For Free button
And New Tab is opened
And User enters SignUp "<firstname>" "<lastname>" "<jobtitle>" information
Then User goes back to home page
And validate home page content
Examples:
| firstname | lastname | jobtitle |
| Kovid |Mehta | Sales Manager |
| Vikas |Bhat | IT Manager |
If you remove dependencies you don't use or pull in transitively and let Maven do the dependency management for you you'll see that you have to replace:
import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.CucumberOptions.SnippetType;
with:
import io.cucumber.testng.CucumberOptions;
import io.cucumber.testng.CucumberOptions.SnippetType;
Currently you can remove:
junit
cucumber-junit
cucumber-jvm-dep
gherkin
cucumber-html
I am trying to implement parallel test execution using cucumber 4.0, but observing issues.
As per details on cucumbers website: https://cucumber.io/docs/guides/parallel-execution/#testng
I included following dependency in pom.xml: (apart from other existing dependencies for testng, etc)
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-jvm</artifactId>
<version>4.4.0</version>
<type>pom</type>
</dependency>
I added following code in runner file:
#Override
#DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
I am seeing following errors on above mentioned code:
The method scenarios() of type Baserunner must override or implement a supertype method. (error on line 62)
The method scenarios() is undefined for the type AbstractTestNGCucumberTests (error on line 63)
If my implementation looks wrong, please let me know!
You should create the one more abstract class like AbstractTestNGCucumberParallelTest within same package and extend to #cucumberOptions annotation like below:
package runner;
import cucumber.api.CucumberOptions;
#CucumberOptions(glue = "stepdefs", features = ".")
public class RunnerIT extends AbstractTestNGCucumberParallelTest{
}
*********************************************
package runner;
import org.testng.annotations.DataProvider;
import cucumber.api.testng.AbstractTestNGCucumberTests;
public abstract class AbstractTestNGCucumberParallelTest extends AbstractTestNGCucumberTests {
#Override
#DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
}
I have created a sample project here is the link below:
https://github.com/racchouhan12/SeleniumCucumber5/blob/master/src/test/java/com/testautomation/test/stepdefinitions/Runners/TestRunner.java.
The TestRunner.java extends AbstractTestNGCucumber class and it uses Cucumber 5.
Also you can match dependencies with above project so in case if any dependencies are missing you can add them.
Here are the cucumber dependencies
<cucumber.version>5.7.0</cucumber.version>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java8</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-core</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
cucumber-java8 dependency requires only if you write lambda style step definitions.
Let me know if it helps.
I am currently trying to achieve parallel test run with cucumber. I managed to run two different runners at the same time with the sure-fire plugin. Now I want to check whether is it possible to run SingleRunner file multiple times in parallel.
Ex: I have SignUpRunnerTest.java so I need to run this against few platforms parally.Is it possible?
This is my Runner file
import cucumber.api.CucumberOptions;
import cucumber.api.cli.Main;
import cucumber.api.junit.Cucumber;
import java.util.List;
import javax.management.MXBean;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
#RunWith(Cucumber.class)
#CucumberOptions(plugin = {"pretty", "html:target/html/", "json:target/cucumber.json", "junit:TEST-all.xml"},
features = "src/test/java/resources/features/Search.feature", glue = {"com.browserstack.stepdefs"})
public class SignUpeRunnerTest {
}
Without Runner Approach
public class SignUpeRunnerTest {
#Test
public void test2() {
Main.main(new String[]{"--threads", "4","-g", "com.browserstack.stepdefs", "src/test/java/resources/features/"});
}
}
Factory Class
`import org.openqa.selenium.WebDriver;
public final class DriverFactory {
private static ThreadLocal<WebDriver> drivers = new ThreadLocal();
//To quit the drivers and browsers at the end only.
private static List<WebDriver> storedDrivers = new ArrayList();
static {
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run(){
storedDrivers.stream().forEach(WebDriver::quit);
}
});
}
private DriverFactory() {}
public static WebDriver getDriver() {
return drivers.get();
}
public static void addDriver(WebDriver driver) {
storedDrivers.add(driver);
drivers.set(driver);
}
public static void removeDriver() {
storedDrivers.remove(drivers.get());
drivers.remove();
}
}
`
Step Class
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class SearchPage {
private static WebDriver webDriver;
public SearchPage(WebDriver webDriver) {
this.webDriver = webDriver;
DriverFactory.addDriver(webDriver);
}
private By searchTermField = By.name("q");
private By submitSearch = By.id("_fZl");
public void enterSearchTerm(String searchTerm) {
DriverFactory.getDriver().findElement(searchTermField).sendKeys(searchTerm);
}
public void submitSearch() {
DriverFactory.getDriver().findElement(submitSearch).click();
}
}
This is my POM file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.browserstack</groupId>
<artifactId>cucumber-jvm-java-browserstack</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cucumber-jvm-java-browserstack</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cucumber.jvm.parallel.version>2.2.0</cucumber.jvm.parallel.version>
<surefire.maven.plugin.version>2.19.1</surefire.maven.plugin.version>
<acceptance.test.parallel.count>4</acceptance.test.parallel.count>
</properties>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>4.2.3</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>datatable</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>4.2.3</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.gfk.senbot/senbot-maven-plugin -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<parallel>methods</parallel>
<threadCount>4</threadCount>
<reuserForks>false</reuserForks>
<testErrorIgnore>true</testErrorIgnore>
<testFailureIgnore>true</testFailureIgnore>
<includes>
<include>**/*RunnerTest.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project>
info.cukes dependency (are pretty old) which support cucumber till v 1.2.5 only and No more support for this after 12 September 2016
Other side, io.cucumber dependency supports Cucumber starting from v 2.0.x till latest v 4.3.x available as of now (Cucumber-JVM 4.0 gives you much flexibility for implementing parallel execution) and below are the steps to implement parallel execution using io.cucumber (Here you do not need to create individual runners per feature file & No need to use any old plug in like jvm-parallel plug in)
1.Adding correct set of dependency. I have followed JUnit during the implementation.
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>4.2.3</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>datatable</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
2.Adding Maven-Surefire-Plugin under POM.XML
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<parallel>methods</parallel>
<threadCount>1</threadCount>
<reuserForks>false</reuserForks>
<testErrorIgnore>true</testErrorIgnore>
<testFailureIgnore>true</testFailureIgnore>
<includes>
<include>**/*RunCukeTest.java</include>
</includes>
</configuration>
</plugin>
Cucumber feature files can be executed without using any runner by using the main() method in class Main of package cucumber.api.cli. Refer to this cli usage and this article. Using this maybe it will work. Need some changes though.
Copy the code of BrowserStackJUnitTest into a new class rename it to something else say NewBSTest. This class will be used for running the test.
Some change will be required in how the driver created for each thread will be accessed by selenium and cucumber code.
Need to use a factory to store the drivers in a ThreadLocal variable in NewBSTest. U can refer to this class.
In the NewBSTest class that u have created remove line no 30 - public WebDriver driver;. Change line 94 to add the created RemoteWebDriver to the ThreadLocal variable. SOmething like DriverFactory.addDriver(driver). Add DriverFactory.removeDriver() in method tearDown() line 98, maybe the first line. Change existing driver.quit(); to DriverFactory.getDriver().quit().
5.Remove the shutdown hook in the DriverFactory, BrowserStack will be quitting the actual driver anyways.
Now in selenium or cucumber code u can access the driver using DriverFactory.getDriver(). This will impact your existing code pretty heavily.
In the NewBSTest class add a test method like this. Hopefully this will work and the same features will be executed in each of the configured browserstack environments.
#Test
public void test() {
Main.main(new String[]{""-g", "stepdef", "src/test/resources/features/"});
}
You might have got answer for this question.To run testcases in parallel ,there are additional settings required as given below in the link-
https://cucumber.io/docs/guides/parallel-execution/
According to this link if you are using surefire plugin, then package name should be parallel for the runner class.
For choosing the device type ,you can add tag for the feature file and further get the tag in before hook. I think for choosing the capability there might be better way available.Below logic is working for me-
#Before(order=2)
public void LaunchBrowser(Scenario sc)
{
String browser= "firefox";
//
ArrayList s = (ArrayList) sc.getSourceTagNames();
//scenarios having this tag will be ignored and not run
if(s.contains("#chrome"))
browser = "chrome";
else if(s.contains("#firefox"))
browser = "firefox";
driverfactory=new DriverFactory();
driver=driverfactory.init_driver(browser);
}
following a tutorial and got stuck with an issue.
System: wildfly 10, maven project with multimodules, packaging: ear
EJB:
#Stateless
public class ToyService implements ToyServiceRemote, ToyServiceLocal {
...
}
INTERFACE:
#Local
public interface ToyServiceLocal {
...
}
BEAN:
#Named("toyProducts")
#RequestScoped
public class ProductBean {
#Inject
private ToyServiceLocal toyService;
#PostConstruct
public void initialize() {
toyList = toyService.getAllToys();
}
...
}
JSF:
<ui:repeat value="#{toyProducts.toyList}" var="toy">
...
</ui:repeat>
The application deploys, but when I try to open the page in browser I am getting:
ERROR [io.undertow.request] (default task-62) UT005023: Exception
handling request to /index.xhtml: javax.servlet.ServletException: Can
not set com.example.common.service.ToyServiceLocal field
shop.beans.ProductBean.toyService to
com.example.product.service.ToyServiceLocal$ToyServiceRemote$1303029808$Proxy$_$$_Weld$EnterpriseProxy$
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
wildfly-experiment | at
io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
wildfly-experiment | at
io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
wildfly-experiment | at
io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
...
I found the "real" answer this time: since I am using multi module maven project, packaged as EAR (with some EJBs, a common JAR and the WAR file). All I had to do was to add scope provided in the WAR file (common is JAR and product in EJB)
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>product</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
We are in the process of migrating our JavaEE app from Weblogic 10.3.6 to Weblogic 12.2.1.2. As part of this migration we are changing our JSF managaged beans to use CDI annotations rather than the standard JSF annotations. #ManagedBean to #Named and javax.faces.bean.ViewScoped to javax.faces.view.ViewScoped. This has proved successful with only minor issues. However I am having a big issue trying to get our tests to run. The tests fail with the following error:
WebBeans context with scope type annotation #ViewScoped does not exist within current thread
I have tried multiple different containers (embedded and remote) but still get this same error. Any help would be much appreciated.
I am using Arquillian with the following pom.xml dependencies:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.1.12.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>arquillian-openejb-embedded</artifactId>
<version>7.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>javax.faces-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.0.13</version>
</dependency>
<dependency>
<groupId>org.primefaces.themes</groupId>
<artifactId>all-themes</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
BackingBean:
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;
#Named
#ViewScoped
public class AnotherBean implements Serializable {
public String doTest()
{
System.out.println("test");
return "test";
}
}
TestBean
#RunWith(Arquillian.class)
public class TestAgain {
#Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class, "test.jar")
.addClass(AnotherBean.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
#Inject
AnotherBean anotherBean;
#Test
public void doTest()
{
Assert.assertEquals(anotherBean.doTest(), "test");
anotherBean.doTest();
}
}
UPDATE
If I change the #Deployment to:
#Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class, "test.jar")
.addClass(AnotherBean.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
I Get:
javax.enterprise.inject.UnsatisfiedResolutionException: Api type [AnotherBean] is not found with the qualifiers
Qualifiers: [#javax.enterprise.inject.Default()]
for injection into Field Injection Point, field name : anotherBean, Bean Owner : [null]
We hat similar difficulties in testing #ViewScoped beans. We solved this by creating the bean with its injections in the test ourselfs.
The Bean instance itself ist created in the test and all dependencies are then inserted into that by using reflection. This works with beans, entitymanger etc
#RunWith(Arquillian.class)
public class ViewControllerTest {
#Inject private OtherBean otherBean;
private ViewController viewController;
#Deployment
public static WebArchive createDeployment() {
return WebArchiveFactory.getDefaultWebarchArchive();
}
#Before
public void setup() throws Exception {
viewController = new ViewController();
TestHelper.setFacesContext(); // provide FacesContextMock
TestHelper.inject(viewController, "otherBean", otherBean);
}
}
With TestHelper looking like this
public class TestHelper {
public static void inject(Object bean,
String fieldName,
Object fieldValue) throws Exception {
if (null == bean) {
throw new IllegalArgumentException("Bean must not be null");
}
Field field;
try {
field = bean.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
log.log(Level.SEVERE, "Could not find field for injection: " + fieldName);
throw e;
}
field.setAccessible(true);
field.set(bean, fieldValue);
}
}
In the end I had to work around this problem with a good old fashioned hack. I found the source for org.apache.webbeans.container.BeanManagerImpl where the original WebBeans context with scope type annotation #ViewScoped does not exist within current thread comes from. I created this class within my test sources and I then made some changes to get around the problem.
Ultimately for my tests I don't care about the scope. I'm testing that the methods run and return the correct logic/data. So in the class it goes and checks what type of scope the bean is in and throws the exception. I simply checked if it was in Viewscoped and if so changed it to Dependent. This then allowed my tests to work.
Not the best solution but it works.