如何自定义zio.test.Assertion的失败消息以输出解码后JSON
自定义ZIO Test断言失败消息的解决方案
你当前使用的基础Assertion.assertion构造方法会直接调用输入值的默认toString方法生成失败提示,因此会输出原始ByteString内容。要自定义输出,我们可以改用支持自定义失败信息的断言构造方式,提前把HttpEntity的字节解码为JSON字符串插入到失败提示中。
调整后的实现代码(适用于ZIO 2.x + Akka HTTP)
import zio.test._ import akka.http.scaladsl.model.HttpEntity import com.jayway.jsonpath.ReadContext import org.hamcrest.Matcher import scala.concurrent.duration._ def isJson(matching: Matcher[_ >: ReadContext]): Assertion[HttpEntity] = Assertion.make[HttpEntity]("isJson", Assertion.param(matching)) { entity => // 1. 先将实体转成严格模式并解码为UTF-8 JSON字符串,超时时间可根据实际情况调整 val decodedJson = scala.concurrent.Await.result( entity.toStrict(5.seconds).map(e => e.data.utf8String)(scala.concurrent.ExecutionContext.global), 10.seconds ) // 2. 保留你原有的断言匹配逻辑 val isMatch: Boolean = { // 你原有test方法的实现,比如用json-path解析decodedJson为ReadContext后用hamcrest匹配 ??? } if (isMatch) BoolAlgebra.success(()) else BoolAlgebra.failure( AssertionValue( assertion = isJson(matching), value = s"""Decoded JSON content: |$decodedJson |""".stripMargin, assertionName = "isJson" ) ) }
效果说明
调整后断言失败时会优先输出解码后的JSON字符串,不再显示原始字节数组,错误提示效果如下:
Decoded JSON content: {"store": {"name": "test", "goods": [...other fields...]}} did not satisfy isJson(with json path "$['store']['name']" equalTo "expectedStore")
适配提示
- 如果你使用的是ZIO 1.x版本,可改用
Assertion.assertionM构造异步断言,配合ZIO的IO操作完成实体解码,不需要手动调用Await - 如果你不需要处理流式HttpEntity,可直接匹配
HttpEntity.Strict类型获取字节数组解码,省略异步转严格实体的逻辑
内容的提问来源于stack exchange,提问作者gervais.b
相关产品推荐
相关产品推荐

