Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JUnit5 issues with Graphene page objects #325

Open
ghost opened this issue Mar 8, 2021 · 3 comments
Open

JUnit5 issues with Graphene page objects #325

ghost opened this issue Mar 8, 2021 · 3 comments

Comments

@ghost
Copy link

ghost commented Mar 8, 2021

Issue Overview

Location navigation using Graphene.goTo doesn't work with arquillian-junit5-container. There's no problem when running with JUnit 4. Maybe, that's also a lifecycle issue like BeforeEach/AfterEach.

Expected Behaviour

Test runs successfully.

Current Behaviour
java.lang.NullPointerException
	at org.jboss.arquillian.graphene.location.LocationEnricher.handleLocationOf(LocationEnricher.java:114)
	at org.jboss.arquillian.graphene.location.LocationEnricher.goTo(LocationEnricher.java:96)
	at org.jboss.arquillian.graphene.DefaultGrapheneRuntime.goTo(DefaultGrapheneRuntime.java:126)
	at org.jboss.arquillian.graphene.DefaultGrapheneRuntime.goTo(DefaultGrapheneRuntime.java:121)
	at org.jboss.arquillian.graphene.Graphene.goTo(Graphene.java:291)
	at org.example.GoogleTest.openGoogle(GoogleTest.java:21) <7 internal calls>
	at org.jboss.arquillian.junit5.ArquillianExtension.interceptBeforeEachMethod(ArquillianExtension.java:100)
Steps To Reproduce

See https://github.com/ChristianHeinemann/arquillian-graphene-junit5-example/tree/main. There is also a branch junit4 for comparison.

Additional Information
<version.arquillian.core>1.7.0.Alpha8</version.arquillian.core>
<version.arquillian.drone>2.5.2</version.arquillian.drone>
<version.arquillian.graphene>2.3.2</version.arquillian.graphene>
<version.arquillian.selenium>3.13.0</version.arquillian.selenium>
<version.junit5>5.7.1</version.junit5>
@ghost
Copy link
Author

ghost commented Mar 8, 2021

It also works if the Graphene.goTo(GooglePage.class) call is moved from the @BeforeEach method to the beginning of the @Test method.

@ghost
Copy link
Author

ghost commented Mar 9, 2021

The problem seems to be that LocationEnricher tries to access GrapheneConfiguration which is stored in the class context managed by org.jboss.arquillian.core.impl.ManagerImpl. When running the test with JUnit 5, only the application context is active in the @BeforeEach method. In contrast, with JUnit 4 the class context, the application context, the suite context and the test context are active.

@Chavelp
Copy link

Chavelp commented Mar 3, 2022

Here is my working workaround which requires Javassist to work. It is just a minimal workaround, since with it, .goTo method is called twice.

package org.jboss.arquillian.junit5;

import java.lang.reflect.Method;

import org.jboss.arquillian.graphene.Graphene;
import org.jboss.arquillian.graphene.page.InitialPage;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;

import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;

/**
 * Con esta clase se pretende solucionar el bug de arquillian con graphene
 * detallado aquí https://github.com/arquillian/arquillian-core/issues/312
 * 
 * @author jlp01
 *
 */
public class ArquillianExtensionBug312Workaround extends ArquillianExtension implements ParameterResolver {

	@Override
	public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
			throws ParameterResolutionException {
		/*
		 * Si está anotado con InitialPage, lo vamos a resolver nosotros
		 */
		return parameterContext.getParameter().isAnnotationPresent(InitialPage.class);
	}

	@Override
	public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
			throws ParameterResolutionException {
		/*
		 * La configuración de graphene no está disponible a esta altura así que tengo
		 * que devolver primero un proxy para que hasta el primer uso no sea cuando
		 * realmente se instancie. Y ahí ya sí está disponible la configuración.
		 * 
		 * Este workaround tiene el problema de que ejecuta 2 veces el .goTo: 1 vez el
		 * propio Graphene que lo hace tarde pero lo hace, y otra aquí.
		 */
		ProxyFactory factory = new ProxyFactory();
		factory.setSuperclass(parameterContext.getParameter().getType());
		Class<?> c = factory.createClass();
		Proxy pagina;
		try {
			pagina = (Proxy) c.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			throw new ParameterResolutionException("No se puede instanciar la página", e);
		}
		pagina.setHandler(new MethodHandler() {

			Object instancia;

			@Override
			public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
				if (instancia == null) {
					instancia = Graphene.goTo(parameterContext.getParameter().getType());
				}

				return thisMethod.invoke(instancia, args); // execute the original method.
			}
		});

		return pagina;
	}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant