2010-12-02 11 views
8

Estoy comenzando con Jersey y tratando de conseguir que Freemarker trabaje con TDD. Quiero hacer un ViewProcessor para mis plantillas, pero no puedo inyectar el contexto de servlet en la clase.Error de inyección del contexto del servlet al usar el marco de prueba de jersey

Aquí es el código de la clase:

@Provider 
public class myProcessor implements ViewProcessor<Template> { 

    [...] 

    @Context 
    public ServletContext myContext; 

    [...] 

freemarkerConfiguration.setTemplateLoader(
     new WebappTemplateLoader(myContext, 
      myContext.getInitParameter("freemarker.template.path"))); 

    [...] 
    } 

Y aquí es el código de prueba:

public class myProcessorTest extends JerseyTest { 

    public static myProcessor mp; 

    public myProcessorTest() throws Exception{ 
     super(new WebAppDescriptor.Builder("com.domain").build()); 
    } 

    @Test 
    public void firstTest(){ 
     mp = new myProcessor(); 
     String path = new String("test.ftl"); 
     Template template = mp.resolve(path); 
     assertNotNull(template); 
    } 
} 

utilizo experto con las dependencias de la siguiente manera:

<dependency> 
    <groupId>com.sun.jersey.jersey-test-framework</groupId> 
    <artifactId>jersey-test-framework-grizzly</artifactId> 
    <version>1.5-SNAPSHOT</version> 
    <scope>test</scope> 
</dependency> 

Mi código funciona muy bien cuando despliego a mi servidor embarcadero local. Pero si quiero probar el código en mi IDE, no logró inyectar el contexto de servlet (@Context): myContext es null cuando corro la prueba:/

Creo que me falta algo, pero yo soy un principiante completo con el mundo servlet.

Respuesta

0

Hay un par de formas de hacerlo. Retire el constructor y poner en práctica un método configure() así:

public class myProcessorTest extends JerseyTest { 

    public static myProcessor mp; 

    @Override 
    protected AppDescriptor configure() { 
    return new WebAppDescriptor.Builder("com.domain") 
     .contextParam("contextConfigLocation", "classpath:/applicationContext.xml") 
     .contextPath("/").servletClass(SpringServlet.class) 
     .contextListenerClass(ContextLoaderListener.class) 
     .requestListenerClass(RequestContextListener.class) 
     .build(); 
    } 

o, alternativamente, puede anotar su prueba con el contexto de la primavera:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:applicationContext.xml") 
public class MyProcessorTest extends JerseyTest { 

    public static myProcessor mp; 
0

Hay una solución a este problema que no requiere primavera, suponiendo que está utilizando el proveedor de marco de prueba Grizzy2 predeterminado/estándar. De acuerdo con this answer, el proveedor del framework jersey-test-framework-provider-grizzly2 no utiliza un entorno de servlet al construir el contexto de la aplicación. Sus síntomas son el resultado de no haber ServletContext instancia para inyectar.

La solución consiste en proporcionar usted mismo el contenedor de prueba para la unidad. En primer lugar, modificar sus dependencias:

<!--<dependency> 
    <groupId>org.glassfish.jersey.test-framework.providers</groupId> 
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId> 
    <version>2.25</version> 
    <scope>test</scope> 
</dependency>--> 
<dependency> 
    <groupId>org.glassfish.jersey.test-framework</groupId> 
    <artifactId>jersey-test-framework-core</artifactId> 
    <version>2.25</version> 
</dependency> 
<dependency> 
    <groupId>org.glassfish.jersey.containers</groupId> 
    <artifactId>jersey-container-grizzly2-servlet</artifactId> 
    <version>2.25</version> 
</dependency> 

A continuación, modifique su ensayo para proporcionar un contenedor de servlets Grizzy:

@Override 
protected TestContainerFactory getTestContainerFactory() throws TestContainerException { 
    return (final URI baseUri, final DeploymentContext deploymentContext) -> 
    new TestContainer() { 
    private HttpServer server = null; 

    @Override 
    public ClientConfig getClientConfig() { 
     return null; 
    } 

    @Override 
    public URI getBaseUri() { 
     return baseUri; 
    } 

    @Override 
    public void start() { 
     try { 
     this.server = GrizzlyWebContainerFactory.create(baseUri, Collections 
      .singletonMap("jersey.config.server.provider.packages", "<your-package-name>")); 
     } catch (final ProcessingException | IOException cause) { 
     throw new TestContainerException(cause); 
     } 
    } 

    @Override 
    public void stop() { 
     this.server.shutdownNow(); 
    } 
    }; 
} 

supongo que se va a utilizar esto en múltiples pruebas de unidad, lo que puede ser sabio extender JerseyTest así que esta configuración común se puede realizar automáticamente. Además, puede valer la pena revisar org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory para ver si hay alguna funcionalidad proporcionada por el contenedor de prueba que desea emular/preservar. El ejemplo proporcionado debería poder soltarse en su prueba para, al menos, confirmar que se trata de una solución.

EDIT: En mi propia implementación, necesitaba la capacidad de seguir suministrando un ResourceConfig al generar el servidor. Sospecho que este es el caso común para otros usuarios de Jersey Test Framework. A continuación se muestra un ejemplo de trabajo del TestContainerFactory propuesto.

import java.io.IOException; 
import java.net.URI; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

import javax.servlet.ServletContext; 
import javax.ws.rs.ProcessingException; 
import javax.ws.rs.core.UriBuilder; 

import org.glassfish.grizzly.http.server.HttpServer; 
import org.glassfish.grizzly.servlet.WebappContext; 
import org.glassfish.hk2.utilities.binding.AbstractBinder; 
import org.glassfish.jersey.client.ClientConfig; 
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; 
import org.glassfish.jersey.test.DeploymentContext; 
import org.glassfish.jersey.test.spi.TestContainer; 
import org.glassfish.jersey.test.spi.TestContainerException; 
import org.glassfish.jersey.test.spi.TestContainerFactory; 
import org.glassfish.jersey.test.spi.TestHelper; 


public class RestTestContainerFactory implements TestContainerFactory {  
    public static class RestTestContainer implements TestContainer { 
    private static final Logger LOGGER = Logger.getLogger(RestTestContainer.class.getName()); 

    private URI baseUri = null; 
    private final HttpServer server; 

    public RestTestContainer(final URI baseUri, final DeploymentContext context) { 
     this.baseUri = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build(); 
     if(LOGGER.isLoggable(Level.INFO)) { 
     LOGGER.info("Creating RestRestContainer configured at the base URI "+TestHelper.zeroPortToAvailablePort(baseUri)); 
     } 

     try { 
     final WebappContext webContext = new WebappContext("TestContext", context.getContextPath()); 
     context.getResourceConfig() 
       .register(new AbstractBinder() { 
       @Override 
       protected void configure() { 
        bind(webContext).to(ServletContext.class); 
       } 
       }); 
     this.server = GrizzlyHttpServerFactory.createHttpServer(this.baseUri, context.getResourceConfig(), false); 
     webContext.deploy(this.server); 

     } catch (final ProcessingException cause) { 
     throw new TestContainerException(cause); 
     } 
    } 

    @Override 
    public ClientConfig getClientConfig() { 
     return null; 
    } 

    @Override 
    public URI getBaseUri() { 
     return baseUri; 
    } 

    @Override 
    public void start() { 
     if(server.isStarted()) { 
     LOGGER.warning("Ignoring start request - RestTestContainer is already started"); 
     } else { 
     LOGGER.fine("Starting RestTestContainer..."); 
     try { 
      server.start(); 
      if(baseUri.getPort() == 0) { 
      baseUri = UriBuilder.fromUri(baseUri) 
       .port(server.getListener("grizzly").getPort()) 
       .build(); 
      LOGGER.info("Started GrizzlyTestContainer at the base URI "+baseUri); 
      } 
     } 
     catch(final ProcessingException | IOException cause) { 
      throw new TestContainerException(cause); 
     } 
     } 
    } 

    @Override 
    public void stop() { 
     if(server.isStarted()) { 
     LOGGER.fine("Stopping RestTestContainer..."); 
     server.shutdownNow(); 
     } else { 
     LOGGER.warning("Ignoring stop request - RestTestContainer is already stopped"); 
     } 
    } 
    } 

    @Override 
    public TestContainer create(final URI baseUri, final DeploymentContext context) { 
    return new RestTestContainer(baseUri,context); 
    } 
} 

frustrante, grisáceo de GrizzlyWebContainerFactory proporcionará un contexto servlet, pero no configurar con una configuración de recursos. Inversamente, GrizzlyHttpServerFactory configurará una aplicación con un ResourceConfig, pero no proporcionará un contexto web.

podemos trabajar en torno a este mediante la creación de la WebappContext (se extiende ServletContext) manualmente, configurar, y luego inyectarla en la configuración de recursos por medio de un AbstractBinder.

Cuestiones relacionadas