这是 Jersey 的标准行为,并且允许基于 servlet 的功能(例如HttpServletRequest)尚不可用。根据我的研究,我可以达到以下条件
- 对整个测试类只初始化一次测试容器
- 将自定义侦听器、过滤器、servlet 等注册到测试容器
- 确保 @Context HttpServletRequest 不为空
通过手动启动/停止 grizzly 容器并将 grizzly 容器实例部署在基于自定义球衣的 WebappContext 上。步骤如下,以防其他人遇到此类问题
- 创建一个 HttpServer
- 在 @Before 创建一个反映您的
web.xml的自定义WebappContext并使用WebappContext部署您的 HttpServer 实例
- 为了确保基于 Servlet 的功能(例如
HttpServletRequest)在集成测试期间可用,请使用ServletRegistration在Servlet 容器中加载您的应用程序,如下所示
步骤1
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ResourceEndpointIntegrationTest{
@Context
private HttpServletRequest httpReq;
private static Logger logger = Logger.getLogger(ResourceEndpointIntegrationTest.class);
public static final String BASE_URI = "http://localhost:8989/";
private static HttpServer server = null;
@BeforeClass
public static void initTest() {
RestAssured.baseURI = "http://localhost:8989/";
}
...
}
使用SpringJUnit4ClassRunner.class和@ContextConfiguration加载applicationContext.xml进行测试。还要声明@Context HttpServletRequest并创建一个HttpServer实例以供以后使用。我在这里使用@BeforeClass用于 Rest-Assured 特定目的(您不必使用它),它是可选的。
第2步
@Before
public void setup() throws Exception {
if (server == null) {
System.out.println("Initializing an instance of Grizzly Container ...");
final ResourceConfig rc = new ResourceConfig(ResourceEndpointIntegrationTest.class, ..., ..., ...); //update
WebappContext ctx = new WebappContext("IntegrationTestContext");
//register your listeners from web.xml in here
ctx.addListener("com.xxx.yyy.XEndpointServletContextListener");
//register your applicationContext.xml here
ctx.addContextInitParameter("contextConfigLocation", "classpath:applicationContext.xml");
//ServletRegistration is needed to load the ResourceConfig rc inside ServletContainer or you will have no
//Servlet-based features available
ServletRegistration registration = ctx.addServlet("ServletContainer",
new ServletContainer(rc));
//Initialize the Grizzly server passing it base URL
server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI));
//Deploy the server using our custom context
ctx.deploy(server);
}
}
@Before中的设置会针对每个测试运行,但是 if 条件将强制设置方法像@BeforeClass一样运行,允许我们为整个测试类初始化一次服务器,减去@BeforeClass的静态特性。
我为测试类中的所有测试初始化服务器一次的原因是,如果我们不这样做,那么我们将有以下工作流程
- 服务器已启动
- Spring开始扫描bean
- Spring 自动装配
- Spring 设置 sessionFactory 等
- 测试运行
- Spring破坏了上下文
- 服务器已关闭
- 对每个测试重复步骤 #1 到 #7
以上非常耗时且技术上不可行,因此初始化容器一次(这就是我不扩展JerseyTest的原因,因为我想控制测试容器的启动/关闭)。
#步骤 3
@AfterClass
public static void tearDown() throws Exception {
System.out.println("Integration tests completed. Tear down the server ...");
if (server != null && server.isStarted()) {
server.shutdownNow();
System.out.println("Grizzly instance shutdown completed");
}
}
在第 3 步中,我们使用@AfterClass关闭用于集成测试目的的 grizzly 实例。
示例测试如下
@Test
public void testCreateSomethingReturnSuccessfully() {
JSONObject something = new JSONObject();
cust.put("name", "integrationTest");
cust.put("age", 33);
given().
contentType(ContentType.JSON).
body(something.toString()).post("/someEndpoint").
then().
statusCode(200).
assertThat().
body("id", greaterThan(0)).
body("name", equalTo("integrationTest")).
body("age", equalTo(33));
}
(Gradle) 一些相关的依赖
compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: '2.23.2'
compile group: 'org.glassfish.jersey.test-framework.providers', name:'jersey-test-framework-provider-grizzly2', version:'2.23.2'
compile group: 'org.springframework', name:'spring-test', version:'4.3.2.RELEASE'
compile group: 'io.rest-assured', name:'rest-assured', version:'3.0.1'
// Spring
compile group: 'org.springframework', name: 'spring-core', version: '4.3.2.RELEASE'
compile group: 'org.springframework', name: 'spring-beans', version: '4.3.2.RELEASE'
compile group: 'org.springframework', name: 'spring-web', version: '4.3.2.RELEASE'
compile group: 'org.springframework', name: 'spring-jdbc', version: '4.3.2.RELEASE'
compile group: 'org.springframework', name: 'spring-orm', version: '4.3.2.RELEASE'
// Jersey-Spring bridge
compile (group: 'org.glassfish.jersey.ext', name: 'jersey-spring3', version: '2.23.2'){
exclude group: 'org.springframework', module: 'spring-core'
exclude group: 'org.springframework', module: 'spring-web'
exclude group: 'org.springframework', module: 'spring-beans'
exclude group: 'org.springframework', module: 'spring-jdbc'
exclude group: 'org.springframework', module: 'spring-orm'
}
部分进口
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Context;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.servlet.ServletRegistration;
import org.glassfish.grizzly.servlet.WebappContext;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;