JerseyTest - 具有泛型类型的 readEntity

问题描述 投票:0回答:1

我有一个通用类,用作 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());
    }
}
java generics java-8 generic-type-argument jersey-test-framework
1个回答
0
投票

首先你需要一些实用类

@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))

© www.soinside.com 2019 - 2024. All rights reserved.