【问题标题】:How to test a Jersey REST web service?如何测试 Jersey REST Web 服务?
【发布时间】:2015-06-04 05:16:42
【问题描述】:

我已经编写了一个 Restful Web 服务,并且必须使用 JUnit4 对其进行测试。我已经使用 Jersey 客户端编写了一个客户端。但想知道我是否只能使用 junit4 测试我的服务。至少有人可以帮我提供样品。

我的休息服务有认证方法,它接受用户名、密码并返回一个令牌。

我已经为验证方法编写了测试用例。但我不确定如何使用 url 进行测试。

public class TestAuthenticate {
    Service service  = new Service();
    String username = "user";
    String password = "password";
    String token;

    @Test(expected = Exception.class)
    public final void testAuthenticateInputs() {
        password = "pass";
        service.authenticate(username, password);
    }

    @Test(expected = Exception.class)
    public final void testAuthenticateException(){
        username = null;
        String token = service.authenticate(username, password);
        assertNotNull(token);
    }

    @Test
    public final void testAuthenticateResult() {
        String token = service.authenticate(username, password);
        assertNotNull(token);
    }
}

【问题讨论】:

  • 如果你想使用 URL 进行测试,那么你需要从你的测试中启动一个服务器。您可以使用嵌入式服务器,这在测试中很常见。或者您可以使用 Jersey 测试框架,它将为您启动一个嵌入式容器。您使用的是哪个泽西岛版本?
  • 检查这个 [问题][1] 它解释了如何模拟你的网络服务。 [1]:stackoverflow.com/questions/31189159/…

标签: java rest unit-testing junit jersey


【解决方案1】:

如果您想使用 URL 进行测试,那么您需要从您的测试中启动一个服务器。您可以显式启动嵌入式服务器,这在测试中很常见。类似的东西

public class MyResourceTest {

    public static final String BASE_URI = "http://localhost:8080/api/";
    private HttpServer server;

    @Before
    public void setUp() throws Exception {
        final ResourceConfig rc = new ResourceConfig(Service.class);
        server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);       
    }

    @After
    public void tearDown() throws Exception {
        server.stop();
    }

    @Test
    public void testService() {
        Client client = ClientBuilder.newClient();
        WebTarget target = client.target(BASE_URI).path("service");
        ...
    }
}

它基本上是一个集成测试。您正在启动 Grizzly 容器并仅使用 Service 类将 ResourceConfig 加载到服务器。当然,您可以在配置中添加更多类。如果需要,您可以使用“真实”资源配置。

上面的测试使用了这个依赖

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-grizzly2-http</artifactId>
    <version>${jersey2.version}</version>
</dependency>

另一个我更喜欢的选项是使用Jersey Test Framework,它将为您启动一个嵌入式容器。测试可能看起来更像

public class SimpleTest extends JerseyTest {
 
    @Override
    protected Application configure() {
        return new ResourceConfig(Service.class);
    }
 
    @Test
    public void test() {
        String hello = target("service").request().get(String.class);
    }
}

使用这个依赖

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>

嵌入式 Grizzly 容器将在后台启动,使用您的 ResourceConfig 配置。在上面的两个示例中,假定 Service 类的 @Path 值为 service,正如您在测试 URL 中看到的那样。

一些资源

一些例子


更新

如果您不使用 Maven,以下是您需要为 Jersey Test Fraemwork 运行嵌入式 Grizzly 容器的 jars

我通常搜索我所有的罐子here。您可以选择版本,下一页应该有一个链接,可以下载。您可以使用搜索栏搜索其他人。

这是一个简单的运行示例,一旦你拥有了所有的 jars

import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.core.DefaultResourceConfig;
import com.sun.jersey.spi.container.servlet.WebComponent;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import junit.framework.Assert;
import org.junit.Test;

public class SimpleTest extends JerseyTest {
    
    @Path("service")
    public static class Service {
        @GET
        public String getTest() { return "Hello World!"; }
    }

    public static class AppConfig extends DefaultResourceConfig {
        public AppConfig() {
            super(Service.class);
        }
    }
    
    @Override
    public WebAppDescriptor configure() {
        return new WebAppDescriptor.Builder()
                .initParam(WebComponent.RESOURCE_CONFIG_CLASS, 
                           AppConfig.class.getName())
                .build();
    }
    
    @Test
    public void doTest() {
        WebResource resource = resource().path("service");
        String result = resource.get(String.class);
        Assert.assertEquals("Hello World!", result);
        System.out.println(result);
    }
}

您很可能没有资源和 ResourceConfig 与测试在同一类中,但我只想保持简单且在一个类中全部可见。

无论您使用的是 web.xml 还是 ResourceConfig 子类(如上所示),您都可以通过使用单独的 ResourceConfig 来减少您测试的内容,就像我所做的那样,内置在测试类中。否则,如果您使用的是普通的 ResourceConfig 类,则可以在 configure 方法中替换它。

configure 方法几乎只是在 Java 代码中构建一个 web.xml 文件。您可以在WebAppDescriptor.Builder 中看到不同的方法,例如initParam,这与您的Web xml 中的&lt;init-param&gt; 相同。您可以简单地在参数中使用字符串,但也有一些常量,就像我在上面使用的那样。

@Test 是您通常会运行的 JUnit 测试。它正在使用泽西客户端。但您无需创建Client,只需访问resource() 方法即可使用预配置的Client,该方法返回WebResource。如果您熟悉 Jersey Client,那么这门课对您来说应该不陌生。

【讨论】:

  • 谢谢,但这很令人困惑。我不能只使用 Junit 和 jmock 来编写测试用例吗?而不是使用这个灰熊容器?我也是 Jmock 的新手。
  • 您能解释一下“使用 url 进行测试”是什么意思吗?我假设您想向 URL 发出请求。如果没有运行该容器来托管 Jersey 应用程序,您将无法做到这一点。除非你的意思是别的。
  • 是的。我必须向ws提出请求。我的ws在tomcat中运行。
  • 所以,现在我明白要访问 Rest web 服务,我们必须使用 JerseyTest 框架或 Rest Assured 框架以及 Junit(不是 req),我们不能单独使用 junit。如果我错了,请纠正我。
  • 出色的解释、用于实施的设置文档以及对这个问题的总体完美回答。这次真是万分感谢。我什至不知道 Jersey 有一个内置的服务器容器可以作为模拟测试配置调用。这使得测试简单服务方法的测试覆盖率变得容易。
【解决方案2】:

看看Alchemy rest client generator。这可以在后台使用 jersey 客户端为您的 JAX-RS Web 服务类生成代理实现。实际上,您会将 Web 服务方法称为单元测试中的简单 Java 方法。也处理 http 身份验证。

如果您只需要简单地运行测试,则不涉及代码生成,因此很方便。

demo here 设置 grizzly 并使用上面的生成器运行 junit 测试。

免责声明:我是这个库的作者。

【讨论】:

    【解决方案3】:

    我认为@peeskillet 为您提供了所需的先决条件,即您需要在嵌入式 Web 服务器中运行您的 Web 服务。您还可以查看 dropwizard 或 spring-boot 支持以方便地执行此操作。

    至于实际验证响应,我会保持简单并使用 JUnit 和 http-matchers(请参阅 https://github.com/valid4j/http-matchers

    【讨论】:

      猜你喜欢
      • 2010-09-17
      • 1970-01-01
      • 2017-01-23
      • 2013-07-16
      • 2012-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多