Arquillian testing JSF with CDI - CDI Scope issue - jsf

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.

Related

Quarkus Unsatisfied dependency for type javax.ws.rs.sse.Sse and qualifiers [#Default]

I try to reproduce https://github.com/volkaert/events-sse-quarkus ; here is an extract :
#ApplicationScoped
#Path("/api-1.0/trevents")
public class SseRealTimeService {
private final Logger log = Logger.getLogger(getClass());
private long id;
private Sse sse;
private SseBroadcaster sseBroadcaster;
public SseRealTimeService(#Context Sse sse,final #Context HttpHeaders httpHeaders) {
this.log.debug(">>>>>>>>>>>>setSse :) " + sse);
this.log.debug(">>>>>>>>>>>>httpHeaders :) " + httpHeaders);
this.sse = sse;
}
...
And I get :
Caused by: javax.enterprise.inject.spi.DeploymentException:
Found 2 deployment problems:
[1] Unsatisfied dependency for type javax.ws.rs.sse.Sse and qualifiers [#Default]
- java member: org.avm.business.rest.api.SseRealTimeService#<init>()
- declared on CLASS bean [types=[org.avm.business.rest.api.SseRealTimeService, java.lang.Object], qualifiers=[#Default, #Any], target=org.avm.business.rest.api.SseRealTimeService]
[2] Unsatisfied dependency for type javax.ws.rs.core.HttpHeaders and qualifiers [#Default]
- java member: org.avm.business.rest.api.SseRealTimeService#<init>()
- declared on CLASS bean [types=[org.avm.business.rest.api.SseRealTimeService, java.lang.Object], qualifiers=[#Default, #Any], target=org.avm.business.rest.api.SseRealTimeService]
As far as I understood, it means it didn't find any class implementing Sse interface which could be injected.
My pom (extract dependencies node) :
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client</artifactId>
</dependency>
<!-- TESTS -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
I have seen this https://github.com/quarkusio/quarkus/issues/6515
but it says v1.5 solved it ; my quarkus version is 1.8.0 (<quarkus.platform.version>1.8.0.Final</quarkus.platform.version> in pom.xml).
I'm lost ... any idea ?

Cucumber execution with TestNG - There were undefined steps

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

The method scenarios() is undefined for the type AbstractTestNGCucumberTests

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.

OmniFaces not destroying ViewScoped bean after closing tab/window

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>

Injecting Stateless EJB into Named Bean

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>

Resources