资讯动态

Hammox typespec支持清单:从union到improper list,20种类型一次讲透

发布时间:2026/8/22 15:31:00 来源:尧图企业网站定制
Hammox typespec支持清单从union到improper list20种类型一次讲透【免费下载链接】hammox automated contract testing via type checking for Elixir functions and mocks项目地址: https://gitcode.com/gh_mirrors/ha/hammoxHammox 是一款面向 Elixir 的 mock 契约测试库它基于typespec 类型检查自动校验你的 mock 和真实实现是否遵守同一份行为契约。本文整理一份完整的Hammox typespec 支持清单从 union 联合类型到 improper list 不规则列表20 种常见类型一次讲透帮你快速了解这款 Elixir 类型检查工具能查什么、怎么查、不匹配时怎么排查。Hammox 是什么30 秒理解契约测试 简单说你定义一个 behaviour 并写清 typespecHammox 就会在测试中动态校验两件事mock 的返回值/参数是否符合 behaviour 的 typespec真实实现模块的返回值/参数是否符合同一份 typespec。它完全兼容 Mox只需把Mox替换成Hammox所有 mock 调用立即获得类型保护。核心类型匹配逻辑全部在lib/hammox/type_engine.ex中报错文案则定义在lib/hammox/type_match_error.ex。Hammox typespec 支持清单20 种类型速览表 #类型Hammox 检查什么1uniona \| b任一分支匹配即通过报错取最深原因栈2any()/term()任意值都通过3none()/no_return()任何返回值都判为不匹配4atom()值必须是 atom5integer()与区间1..10整数值及范围6有符号整数族pos_integer()/neg_integer()/non_neg_integer()的正负边界7float()与number()浮点数number 允许整数或浮点8boolean()/bool()仅true/false9binary()与 bitstring8 位对齐的二进制支持_::3、_::_*3等位字面量10charlist()/nonempty_charlist()字符码点列表字符串会被拒绝11list(t)每个元素都需匹配t空列表通过12nonempty_list(t)元素匹配且列表不能为空13map()与 map 字面量%{key: atom()}、required()/optional()键的必填与类型14struct()与 struct 字面量结构体类型、结构体名称及各字段类型15tuple()任意元组{:ok, atom()}逐元素检查16keyword(t)[{atom, t}, ...]形式的键值列表17iolist()/iodata()递归的嵌套 IO 数据可含不规则列表18fun()函数存在性 元数arity匹配19字面量类型atom 字面量、整数/负整数/区间字面量、空列表[]、[atom(), ...]等20improper list 族maybe_improper_list/2、nonempty_improper_list/2、nonempty_maybe_improper_list/2除以上 20 种外Hammox 还支持协议类型如Enumerable.t()会真正检查值是否实现了该协议、远程类型MyModule.t()及带参远程类型、用户自定义类型type/typep/opaque支持嵌套参数解析、record()、命名参数注解类型arg :: type()、以及mfa()、module()、identifier()、timeout()、byte()、char()、arity()、as_boolean(t)等类型。标量类型Hammox 检查得很细 atom 与 atom 字面量atom()接受任意 atom而:ok这样的字面量只接受:ok本身。整数integer()会拒绝1.0这类浮点1..10区间与-1负数字面量也都能精确匹配。有符号整数族0不满足pos_integer()-1.0不满足neg_integer()边界检查很严格。booleannil会被boolean()拒绝只认true和false。binary 与 bitstringbinary()要求 8 位对齐1::7会失败而bitstring()则放行。位字面量如_::size(3)会校验精确位数。charlist[65]通过字符串A会被拒绝——这是新手最容易踩的坑。容器类型list、map、struct、tuple 一次看懂 list 与 nonempty_list 的区别list(atom())允许[]nonempty_list(atom())遇到空列表会报 Got an empty list but expected ...。元素类型不匹配时报错会精确指出第几个索引的哪个元素出了问题。map 字面量required 与 optional%{key: atom()}必填键缺键、多出的未知键、值类型错误都会报错%{required(atom()) atom(), optional(number()) number()}混合必填/可选键Hammox 会做命中匹配能处理重叠的键类型缺必填字段时提示 Could not find a map entry matching ...带:__struct__键的 map 会按结构体语义校验结构体名称与字段。struct 与 tuplestruct()接受任何结构体、拒绝普通 map%MyStruct{foo: number()}则连字段类型一起查。元组按大小和每个位置逐一匹配{:ok, atom()}收到{:error, :reason}会立刻指出第 1 个元素类型不对。难点攻坚improper list 为什么值得单独讲 improper list不规则列表指尾部不是[]的列表例如[:a | :b]。Hammox 对三种写法全部支持类型[][:a][:a \| :b]maybe_improper_list(:a, :b)✅✅✅nonempty_improper_list(:a, :b)❌❌✅nonempty_maybe_improper_list(:a, :b)❌✅✅检查时 Hammox 会递归验证每个头部元素是否为:a并单独校验尾部终止符是否为:b。如果尾部错了你会看到专门的报错** (Hammox.TypeMatchError) Returned value [:a | :a] does not match type nonempty_improper_list(:a, :b). Improper list terminator :a does not match terminator type :b.这种列表尾部类型级别的诊断是很多 Elixir 静态检查工具做不到的。union 类型与字面量多个契约怎么办 union 联合类型{:ok, [binary()]} | {:error, term()}这类返回值任一分支匹配即通过。Hammox 的贴心之处在于当 union 全部失败时它会选择原因栈最深的那条错误链输出直接告诉你错在哪一层而不是只报个笼统的类型不符。字面量与多条 typespec函数字面量(- :ok)、(:a, :b - :ok)会按元数检查... - :ok接受任意元数同一个函数可以声明多条 typespec重载式写法Hammox 逐条尝试全部不匹配才报错并保留最详细的原因栈。如何读懂 TypeMatchError 报错信息 ️所有不匹配都会抛出Hammox.TypeMatchError定义见lib/hammox/type_match_error.ex消息是分层缩进的先说结论、再给细节参数错误1st argument value bar does not match 1st parameters type atom()命名参数还会附带参数名返回值错误Returned value ... does not match type ...容器细节Element 1 at index 1 does not match element type ...、Map key ... does not match map key type ...结构体细节Expected the value to be a MyStruct, got a OtherStruct.协议细节Value :atom does not implement the Enumerable protocol.排查思路先看第一行确定是参数还是返回值再看缩进最深的子行定位具体字段/索引。3 步快速上手 Hammox 类型检查 第 1 步获取项目git clone https://gitcode.com/gh_mirrors/ha/hammox第 2 步添加依赖见mix.exs仅用于测试环境{:hammox, ~ 0.7, only: :test}第 3 步替换 Mox 或启用 protect已有 Mox 项目把import Mox换成import Hammox即可所有expect/4、stub/3自动获得类型校验保护真实实现Hammox.protect({Module, :func, 0}, Behaviour)返回一个受保护函数批量保护可用Hammox.protect(Implementation, Behaviour)返回适合setup_all的 map更省事use Hammox.Protect, module: Implementation, behaviour: Behaviour像import一样直接使用受保护函数实现见lib/hammox/protect.ex。类型定义与校验行为的完整示例可参考test/support/behaviour.ex测试覆盖见test/hammox_test.exsHammox 的 Telemetry 事件说明见guides/Telemetry.md。已知限制与常见问题 ❓匿名函数参数/返回值不检查fun()类型只校验是否存在函数及元数是否正确参数类型和返回类型暂不校验arity 上限为 253BEAM 限制函数最多 255 个参数保护包装器占用 2 个因此超过 253 元数的函数无法被 protect必须能找到 typespec被保护函数若没有对应的 typespec会抛出TypespecNotFoundError提示你去补上类型声明与 Dialyzer 不冲突Dialyzer 是静态分析、查不到 mock 场景Hammox 是动态契约校验二者互补。总结这份 Hammox typespec 支持清单覆盖了从 union、标量、容器到 improper list 的 20 种核心类型外加协议、远程与用户自定义类型。它的核心价值一句话让 mock 和真实实现遵守同一份类型契约并把类型错误在测试期就变成清晰的中文式报错。如果你正在用 Mox迁移成本几乎为零却能让 Elixir 单测的可靠性直接上一个台阶。【免费下载链接】hammox automated contract testing via type checking for Elixir functions and mocks项目地址: https://gitcode.com/gh_mirrors/ha/hammox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价