You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 04:36:06