使用 Quarkus 和 RestAssured 模拟一个 JSON 请求参数

Mock a JSON request parameter using Quarkus and RestAssured

使用 Quarkus,我有以下 API。

@RequestScoped
@Path("/api/v1")
public class MyApi {

    @POST
    @Consumes(APPLICATION_JSON)
    public Response create(Entity entityToCreate) {
        if (entityToCreate.isValid()) {
            // create the entity in my app...
            return Response.ok().build();
        } else {
            return Response.status(BAD_REQUEST).build();
        }
    }
}

我的Entityclass看起来像这样

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Entity {

    private final String property1;
    private final String property2;
    // ...

    @JsonCreator
    public Entity(@JsonProperty("property1") String property1,
                  @JsonProperty("property2") String property2,
                  // ...
    ){
        this.property1 = property1;
        this.property2 = property2;
        // ...
    }

    // getters for every property...

    public boolean isValid() {
        // check if the entity is valid, then return true or false
    }
}

我想在单元测试中实现以下目标:

import static io.restassured.RestAssured.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@QuarkusTest
public class MyApiTest {
    
    private final Entity entityMock = mock(Entity.class);
    
    @Test
    public void shouldCreateEntityWhenValid(){
        when(entityMock.isValid()).thenReturn(true);

        given()
            .contentType(ContentType.JSON)
            .body(entityMock)
        .when()
            .post("/api/v1")
        .then()
            .statusCode(200);
    }

    @Test
    public void shouldNotCreateEntityWhenInvalid(){
        when(entityMock.isValid()).thenReturn(false);

        given()
            .contentType(ContentType.JSON)
            .body(entityMock)
        .when()
            .post("/api/v1")
        .then()
            .statusCode(400);
    }
}

目前,我遇到了以下错误,因为 Jackson 试图反序列化模拟。

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.invocation.mockref.MockWeakReference and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: blah blah blah... )

只需创建实体的真实实例并进行验证。

Rest Assured 将 post 测试中的实际 HTTP 请求,因此它将您的模拟序列化为 JSON。当实现处理 HTTP 请求时,请求正文将反序列化为一个实体。该实体是在内部实例化的,因此它与测试中创建的实例不同。

我最终混合了几种测试技术,以验证 JSON 映射和方法行为。

import static io.restassured.RestAssured.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@QuarkusTest
public class MyApiTest {
    
    private final Entity entityMock = mock(Entity.class);
    private final Entity validEntity = // [...] instantiate a valid entity here
    
    private MyApi api;
    
    @BeforeEach
    void beforeEach() {
        myApi = new MyApi();
    }    

    // this test validates both the JSON parsing and the valid entity case
    @Test
    public void shouldCreateEntityWhenValid(){ 
        given()
            .contentType(ContentType.JSON)
            .body(validEntity)
        .when()
            .post("/api/v1")
        .then()
            .statusCode(200);
    }
    
    // this test validates the invalid entity case
    @Test
    public void shouldNotCreateEntityWhenInvalid(){
        when(entityMock.isValid()).thenReturn(false);

        Response response = myApi.create(entityMock);

        assertThat(response.getStatus()).isEqualTo(400);
    }
}