【问题标题】:How test @WebServlet with Jersey Test Framework? (Throws Http 404 not found)如何使用 Jersey 测试框架测试 @WebServlet? (抛出 Http 404 not found)
【发布时间】:2017-07-06 23:44:12
【问题描述】:

当我使用 Jersey 测试框架为具有 @Path 的类运行我的 Maven 测试时,它运行良好。但是当我尝试测试 @WebServlet 类时,它没有,并说这是一个 404 错误。

如何使用 Jersey 测试框架测试 Web servlet? (或者,如果这是不可能的,我还能如何测试呢?)

Web Servlet:

package com.testservlet;


@WebServlet("/test")
public class TestServlet extends HttpServlet
{

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        resp.getWriter().println( "The Result" );
    }
}

测试类:

import com.testservlet.TestServlet;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;

import javax.ws.rs.core.Application;

public class TestEndpoint extends JerseyTest
{
    @Override
    protected Application configure()
    {
        return new ResourceConfig( JPAServlet.class );
    }

    @Test
    public void baseGetTest()
    {
        String response = target( "/test" ).request().get( String.class );
        Assert.assertTrue( "92096".equals( response ) );
    }
}

马文:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>TestWeb</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>war</packaging>

    <!-- Tell Maven what language version to use -->
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>


    <dependencies>

        <!-- Enables the annotations, etc needed -->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.exterprise</groupId>
                    <artifactId>cdi-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Our jersey libs -->
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>2.25.1</version>
        </dependency>

        <!-- CDI to JAX-RS Binding -->
        <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers.glassfish/jersey-gf-cdi-ban-custom-hk2-binding -->
        <dependency>
            <groupId>org.glassfish.jersey.containers.glassfish</groupId>
            <artifactId>jersey-gf-cdi</artifactId>
            <version>2.14</version>
        </dependency>

        <!-- TESTING WEB -->
        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-jdk-http</artifactId>
            <version>2.25.1</version>
        </dependency>

    </dependencies>

</project>

【问题讨论】:

    标签: java maven jakarta-ee jersey jersey-test-framework


    【解决方案1】:

    首先,您需要使用支持 servlet 部署的 container,例如 grizzly 容器

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

    然后您需要配置测试类以部署为 servlet 容器。

    @Override
    public TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }
    
    @Override
    public DeploymentContext configureDeployment() {
        return ServletDeploymentContext.forServlet(TestServlet.class)
                .build();
    }
    

    在这里,您不需要像当前所做的那样覆盖 configure 方法。但是,上述配置并未配置 Jersey 应用程序。它只配置您的测试 servlet。如果你想在 servlet 环境中运行 Jersey(默认 JerseyTest 不这样做),那么你可以像配置 Jersey 一样

    @Override
    public DeploymentContext configureDeployment() {
        final ResouceConfig config = ResourceConfig();
        return ServletDeploymentContext.builder(config)
                .build();
    }
    

    您可以使用ServletDeploymentContext 配置许多其他内容;看看文档吧。

    更新

    而不是尝试启动服务器。您最好编写一个 unit 测试(而不是 integration 测试),并使用像 Mockito 这样的模拟框架来模拟依赖项。下面有一个例子。我对每一行的作用添加了一些评论。有关 Mockito 的更多信息,请参阅链接文档。

    public class WebServletTest {
    
        @Test
        public void testServletGet() throws Exception {
            // create some mocks
            SomeDao dao = mock(SomeDao.class);
            HttpServletRequest request = mock(HttpServletRequest.class);
            HttpServletResponse response = mock(HttpServletResponse.class);
            PrintWriter writer = mock(PrintWriter.class);
    
            // do some stubbing
            when(response.getWriter()).thenReturn(writer);
            when(dao.getData(anyString())).thenReturn("Hello World");
            // used to capture argument to writer.println
            ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
    
            // create the servlet and call the method under test
            TestServlet servlet = new TestServlet(dao);
            servlet.doGet(request, response);
    
            // capture the argument to writer.println
            verify(writer).println(captor.capture());
            String arg = captor.getValue();
    
            // make assetions
            assertThat(arg).isEqualTo("Hello World");
        }
    
        private interface SomeDao {
            String getData(String param);
        }
    
        @WebServlet("/test")
        public static class TestServlet extends HttpServlet {
            private final SomeDao dao;
    
            @Inject
            public TestServlet(SomeDao dao) {
                this.dao = dao;
            }
    
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                    throws ServletException, IOException {
                resp.getWriter().println(this.dao.getData(""));
            }
        }
    }
    

    【讨论】:

    • 这对我不起作用。收到 500 错误,表示无法连接。 public class TestWebServlet2 extends JerseyTest { @Override public TestContainerFactory getTestContainerFactory() { return new GrizzlyWebTestContainerFactory(); } @Override public DeploymentContext configureDeployment() { return ServletDeploymentContext.forServlet(TestServlet.class) .build(); } @Test public void baseGetTest() { String response = target( "/test" ).request().get( String.class ); Assert.assertTrue( "92096".equals( response ) ); } }
    • 我在测试时工作得很好。有堆栈跟踪吗?如果没有,请尝试写一个generic exception mapper 尝试记录它
    • 啊,看来是这样做的,它不能做 JPA(在我的 servlet 中使用)。错误:javax.servlet.ServletException: &lt;openjpa-2.4.2-r422266:1777108 fatal user error&gt; org.apache.openjpa.persistence.ArgumentException: The persistence provider is attempting to use properties in the persistence.xml file to resolve the data source. A Java Database Connectivity (JDBC) driver or data source class name must be specified in the openjpa.ConnectionDriverName or javax.persistence.jdbc.driver property. The following properties are available in the configuration
    • 只需使用 mock 对 servlet 进行单元测试。不需要运行服务器。您可以模拟 EntityMananger,也可以模拟 HttpServlet(Request|Response)。使用 Mockito 作为您的模拟库。
    猜你喜欢
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 2019-01-04
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多