使用 Rest-Assured 提取嵌套的 POJO 对象
Extracting Nested POJO Object with Rest-Assured
我正在使用 rest-assured 及其 Kotlin 扩展编写一些测试来测试一些简单的 Spring MVC 端点。我正在尝试了解如何提取值。
一个端点returns一个BookDetailsView
POJO,另一个returns一个Page<BookDetailsView>
(其中Page
是Spring提供的接口用于分页)。
BookDetailsView
是一个非常简单的 Kotlin 数据 class,只有一个字段:
data class BookDetailsView(val id: UUID)
对于单个对象端点,我有:
@Test
fun `single object`() {
val details = BookDetailsView(UUID.randomUUID())
whenever(bookDetailsService.getBookDetails(details.id)).thenReturn(details)
val result: BookDetailsView = Given {
mockMvc(mockMvc)
} When {
get("/book_details/${details.id}")
} Then {
statusCode(HttpStatus.SC_OK)
} Extract {
`as`(BookDetailsView::class.java)
}
assertEquals(details.id, result.id)
}
这按预期工作,但尝试对 Page<BookDetailsView>
应用相同的技术会遇到各种解析挑战,因为 Page 是一个接口,甚至尝试使用 PageImpl
也不是'完全简单。最后,我什至不关心 Page
对象,我只关心它里面嵌套的 POJO 列表。
我已经尝试了各种排列,例如下面的代码,只抓住了我关心的部分:
@Test
fun `extract nested`() {
val page = PageImpl(listOf(
BookDetailsView(UUID.randomUUID())
))
whenever(bookDetailsService.getBookDetailsPaged(any())).thenReturn(page)
val response = Given {
mockMvc(mockMvc)
} When {
get("/book_details")
} Then {
statusCode(HttpStatus.SC_OK)
body("content.size()", `is`(1))
body("content[0].id", equalTo(page.first().id.toString()))
} Extract {
path<List<BookDetailsView>>("content")
}
println(response[0].javaClass)
}
最终println
吐出class java.util.LinkedHashMap
。相反,如果我尝试实际使用该对象,我会得到 class java.util.LinkedHashMap cannot be cast to class BookDetailsView
。有很多与此相关的问题和答案,我知道这最终是底层 JSON 解析器不知道该怎么做的问题,但我不清楚:
- 为什么“简单”案例解析没有问题?
- 传递给
path()
函数的类型参数不应该告诉它使用什么类型吗?
- 需要配置什么才能使第二种情况起作用,或者
- 是否有其他更有意义的获取嵌套对象的方法?
深入研究一下代码,似乎这两种情况实际上可能使用了不同的json parsers/configurations(前者似乎坚持放心的JSON解析,而后者最终出现在 JsonPath 中?)
我不知道科特林,但事情是这样的:
path()
不知道列表中的元素,因此默认情况下它将是 LinkedHashMap
而不是 BookDetailsView.class
为了克服它,你可以为此提供 TypeReference。
java 例子
List<BookDetailsView> response = ....then()
.extract().jsonPath()
.getObject("content", new TypeRef<List<BookDetailsView>>() {});
科特林示例
@Test
fun `extract nested`() {
var response = RestAssured.given().get("http://localhost:8000/req1")
.then()
.extract()
.jsonPath()
.getObject("content", object : TypeRef<List<BookDetailsView?>?>() {});
println(response)
//[{id=1}, {id=2}]
}
我正在使用 rest-assured 及其 Kotlin 扩展编写一些测试来测试一些简单的 Spring MVC 端点。我正在尝试了解如何提取值。
一个端点returns一个BookDetailsView
POJO,另一个returns一个Page<BookDetailsView>
(其中Page
是Spring提供的接口用于分页)。
BookDetailsView
是一个非常简单的 Kotlin 数据 class,只有一个字段:
data class BookDetailsView(val id: UUID)
对于单个对象端点,我有:
@Test
fun `single object`() {
val details = BookDetailsView(UUID.randomUUID())
whenever(bookDetailsService.getBookDetails(details.id)).thenReturn(details)
val result: BookDetailsView = Given {
mockMvc(mockMvc)
} When {
get("/book_details/${details.id}")
} Then {
statusCode(HttpStatus.SC_OK)
} Extract {
`as`(BookDetailsView::class.java)
}
assertEquals(details.id, result.id)
}
这按预期工作,但尝试对 Page<BookDetailsView>
应用相同的技术会遇到各种解析挑战,因为 Page 是一个接口,甚至尝试使用 PageImpl
也不是'完全简单。最后,我什至不关心 Page
对象,我只关心它里面嵌套的 POJO 列表。
我已经尝试了各种排列,例如下面的代码,只抓住了我关心的部分:
@Test
fun `extract nested`() {
val page = PageImpl(listOf(
BookDetailsView(UUID.randomUUID())
))
whenever(bookDetailsService.getBookDetailsPaged(any())).thenReturn(page)
val response = Given {
mockMvc(mockMvc)
} When {
get("/book_details")
} Then {
statusCode(HttpStatus.SC_OK)
body("content.size()", `is`(1))
body("content[0].id", equalTo(page.first().id.toString()))
} Extract {
path<List<BookDetailsView>>("content")
}
println(response[0].javaClass)
}
最终println
吐出class java.util.LinkedHashMap
。相反,如果我尝试实际使用该对象,我会得到 class java.util.LinkedHashMap cannot be cast to class BookDetailsView
。有很多与此相关的问题和答案,我知道这最终是底层 JSON 解析器不知道该怎么做的问题,但我不清楚:
- 为什么“简单”案例解析没有问题?
- 传递给
path()
函数的类型参数不应该告诉它使用什么类型吗? - 需要配置什么才能使第二种情况起作用,或者
- 是否有其他更有意义的获取嵌套对象的方法?
深入研究一下代码,似乎这两种情况实际上可能使用了不同的json parsers/configurations(前者似乎坚持放心的JSON解析,而后者最终出现在 JsonPath 中?)
我不知道科特林,但事情是这样的:
path()
不知道列表中的元素,因此默认情况下它将是LinkedHashMap
而不是BookDetailsView.class
为了克服它,你可以为此提供 TypeReference。
java 例子
List<BookDetailsView> response = ....then()
.extract().jsonPath()
.getObject("content", new TypeRef<List<BookDetailsView>>() {});
科特林示例
@Test
fun `extract nested`() {
var response = RestAssured.given().get("http://localhost:8000/req1")
.then()
.extract()
.jsonPath()
.getObject("content", object : TypeRef<List<BookDetailsView?>?>() {});
println(response)
//[{id=1}, {id=2}]
}