如何在内存单元测试Spring-Jersey

时间:2015-02-19 19:09:20

标签: spring unit-testing junit jersey jersey-2.0

我正在使用Spring-Jersey3,无法弄清楚如何使用Spring bean对RESTFul API进行单元测试

控制器

package com.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.service.DataSource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("test")
@Component
public class SpringController {
    @Autowired
    private DataSource datasource;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getHello() {
        return new String(datasource.load());
    }
}

服务接口

package com.service;

public interface DataSource {
    public String load();
}

服务实施

package com.service;

import org.springframework.stereotype.Repository;

@Repository
public class DataSourceImpl implements DataSource {

    @Override
    public String load() {
        return "Hello";
    }
}

ResourceRegister.java(泽西资源注册)

package com.component;

import org.glassfish.jersey.server.ResourceConfig;
import com.controller.SpringController;

public class ResourceRegister extends ResourceConfig {

    public ResourceRegister () {
        register(SpringController.class);
    }
}

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:applicationContext.xml</param-value>
</context-param>

<servlet>
  <servlet-name>Jersey</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
  <param-name>javax.ws.rs.Application</param-name>
  <param-value>com.component.ResourceRegister</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>Jersey</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

serviceContext.xml(应用程序上下文)

<?xml version="1.0" encoding="UTF-8"?>

<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="com.service" />
<context:component-scan base-package="com.controller" />

</beans>

单元测试&lt;&lt; - 我真的不知道如何测试这个

public class test extends JerseyTest {
    public test() {
        super("com.service", "com.controller");
    }

    @Override
    protected AppDescriptor configure() {
        return new WebAppDescriptor.Builder("com.service","com.controller")
               .contextParam("contextConfigLocation", "classpath:serviceContext.xml")
               .contextPath("/rest")
               .servletClass("org.glassfish.jersey.servlet.ServletContainer.class")
               .initParam("javax.ws.rs.Application", "com.component.ResourceRegister")
               .build();
    }

    @Test
    public void test() {
        Client client = new Client();
        WebResource resource = client.resource("test");

        ClientResponse response = resource.post(ClientResponse.class);

        assertEquals(200, resposne.getStatus());
    }
}

项目Source Code

问题:依赖注入返回null

1 个答案:

答案 0 :(得分:14)

我要解决的一些事情:

  • 您正在使用Jersey 1.x风味的Jersey测试框架,但您的应用是Jersey 2.x.请参阅下面的2.x依赖。

  • 我从未使用Jersey 1.x风格的测试框架,但是对于Jersey 2.x,In-Memory container不支持servlet相关功能。请参阅下文了解不同的依赖关系。

  • 使用Jersey Test Framework,您无需自己创建Client。创建了一个,我们可以简单地调用JerseyTest的{​​{1}}方法来获取target(String path)(泽西岛2.x,WebTarget是泽西岛1.x)< / p>

这是一个有效的重构器。

依赖性(我只添加了这个依赖项,并没有采取任何措施,因为你的GitHub项目没有包含任何与测试相关的内容,正如上面的代码示例所做的那样)

WebResource

测试

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>2.15</version>
</dependency>

对于那些不使用xml上下文文件的人,可以使用注释配置应用程序上下文,并将其添加为init参数

import com.component.ResourceRegister;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.web.context.ContextLoaderListener;

public class SpringTest extends JerseyTest {

    @Override
    protected TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }

    @Override
    protected DeploymentContext configureDeployment(){
        return ServletDeploymentContext
                .forServlet(new ServletContainer(new ResourceRegister()))
                .addListener(ContextLoaderListener.class)
                .contextParam("contextConfigLocation", "classpath:applicationContext.xml")
                .build();
    }

    @Test
    public void test() {
        String response = target("test").request().get(String.class);
        Assert.assertEquals("Hello", response);
        System.out.println(response);
    }  
}

其他资源:


更新

经过几次测试后,我发现了一些有趣的事情

一:

有了上述依赖关系,即使我们没有配置return ServletDeploymentContext .forServlet(new ServletContainer(new ResourceRegister())) .addListener(ContextLoaderListener.class) .initParam("contextConfig", new AnnotationConfigApplicationContext(YourSpringConfig.class)) .build(); ,也只是覆盖DeploymentContext中的Application configure(),它仍然有效。无法解释它,但似乎描述符仍然被拾取。

JerseyTest

两个

即使我们摆脱了上述依赖(灰熊)并使用内存依赖,同样简单的先前测试也可以。文档说明

  

内存容器不是真正的容器。它启动Jersey应用程序并直接调用内部API来处理由测试框架提供的客户端创建的请求。没有涉及网络通信。此容器不支持servlet和其他容器相关的功能,但它是简单单元测试的完美选择。

所以我不完全确定他们所指的Servlet功能,因为这个测试仍然有效

import javax.ws.rs.core.Application;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;

public class SpringTest extends JerseyTest {

    @Override
    public Application configure() {
        return new ResourceConfig().packages("com.controller");
    }

    @Test
    public void test() {
        String response = target("test").request().get(String.class);
        Assert.assertEquals("Hello", response);
        System.out.println(response);
    }  
}

我特别不明白的是这句话

  

“没有涉及网络通信”

因为当我运行测试时,我会看到一个日志

  

<dependency> <groupId>org.glassfish.jersey.test-framework.providers</groupId> <artifactId>jersey-test-framework-provider-inmemory</artifactId> <version>2.15</version> </dependency>