我有一个通用类,用作 API 中所有资源的响应
public class TestResponse<T> {
private boolean result;
private int status;
private T data;
// Getters and Setters
}
我还有两个类,用于从两个不同的资源实例化
TestResponse.Data
字段
public class TestResponseData01 {
private int id;
// Getters and Setters
}
public class TestResponseData02 {
private String message;
// Getters and Setters
}
一个资源返回
TestResponse<TestResponseData01>
类型的响应,另一个 TestResponse<TestResponseData02>
在测试类中,我创建了一个方法来运行所有资源响应的常见测试,但我想返回 TestResponse 实例,以便我可以根据我正在测试的资源运行特定测试。
private <T> TestResponse<T> commonTest(Response response, Class<T> dataType) {
TestResponse<T> testResponse = response.readEntity(new GenericType<TestResponse<T>>(){});
// ...
}
问题在于语句
TestResponse<T> testResponse = response.readEntity(new GenericType<TestResponse<T>>(){})
反序列化响应 JSON,但对于 TestResponse.Data
字段,它实例化了 java.util.LinkedHashMap
类型的对象
如何执行 readEntity 方法,以便使用
TestResponse.Data
或 TestResponseData01
正确实例化 TestResponseData02
字段?
完整代码
pom.xml 依赖项
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lombok.version>1.18.30</lombok.version>
<jersey.version>2.25.1</jersey.version>
<junit.version>5.11.2</junit.version>
</properties>
<dependencies>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Jersey Test -->
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
泽西测试班
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@TestInstance(Lifecycle.PER_CLASS)
public class Test_GenericType extends JerseyTest {
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
public static class TestResponse<T> {
private boolean result;
private int status;
private T data;
}
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
public static class TestResponseData01 {
private int id;
}
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
public static class TestResponseData02 {
private String message;
}
@Path("testData01")
@Produces(MediaType.APPLICATION_JSON)
public static class TestResponseData01Resource {
@GET
public Response test() {
TestResponseData01 testResponseData01 = new TestResponseData01(1);
TestResponse<TestResponseData01> testResponse = new TestResponse<TestResponseData01>(true, Response.Status.OK.getStatusCode(), testResponseData01);
return Response.status(Response.Status.OK).entity(testResponse).build();
}
}
@Path("testData02")
@Produces(MediaType.APPLICATION_JSON)
public static class TestResponseData02Resource {
@GET
public Response test() {
TestResponseData02 testResponseData02 = new TestResponseData02("a");
TestResponse<TestResponseData02> testResponse = new TestResponse<TestResponseData02>(true, Response.Status.OK.getStatusCode(), testResponseData02);
return Response.status(Response.Status.OK).entity(testResponse).build();
}
}
@Override
protected Application configure() {
return new ResourceConfig(TestResponseData01Resource.class, TestResponseData02Resource.class);
}
@BeforeAll
public void before() throws Exception {
super.setUp();
}
@AfterAll
public void after() throws Exception {
super.tearDown();
}
private <T> TestResponse<T> commonTest(Response response, Class<T> dataType) {
TestResponse<T> testResponse = response.readEntity(new GenericType<TestResponse<T>>(){});
assertTrue(testResponse.isResult());
assertEquals(200, testResponse.getStatus());
return testResponse;
}
@Test
void Test_ResponseData01Resource() {
Response response = target("testData01").request().get();
TestResponse<TestResponseData01> testResponse = commonTest(response, TestResponseData01.class);
TestResponseData01 testData = testResponse.getData();
assertEquals(1, testData.getId());
}
@Test
void Test_ResponseData02Resource() {
Response response = target("testData02").request().get();
TestResponse<TestResponseData02> testResponse = commonTest(response, TestResponseData02.class);
TestResponseData02 testData = testResponse.getData();
assertEquals("a", testData.getMessage());
}
}
首先你需要一些实用类
@RequiredArgsConstructor
class MyType implements Type {
private final Class c;
@Override
public String getTypeName() {
return c.getTypeName();
}
}
class MyParameterizedType implements ParameterizedType {
private Type[] types;
private final MyType myType;
private MyParameterizedType(Class clz, Class... params) {
types = Arrays.stream(params).map(MyType::new).toArray(Type[]::new);
myType = new MyType(clz);
}
@Override
public Type[] getActualTypeArguments() {
return types;
}
@Override
public Type getRawType() {
return myType;
}
@Override
public Type getOwnerType() {
return null;
}
}
那就简单了
new GenericType(new MyParameterizedType(TestResponse.class, dataType))
。