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

Elixir测试宏开发:解决do:block无法获取正确变量的问题

Elixir test_ok宏作用域问题排查与解决

问题根源

你的两个问题本质都是宏的作用域绑定问题:

  1. response变量无法识别:你传入的do:block属于调用宏时的作用域,而宏内部定义的response是在宏展开后生成的测试函数作用域里,两者上下文不共享,所以block找不到这个变量。
  2. setup的count变量无法访问:自定义宏生成的测试代码没有正确接收测试上下文(context),而setup定义的变量是存在于context中的,正常test宏会自动处理上下文传递,你的宏没做这一步。

修复方案

下面是调整后的宏示例,解决两个作用域问题:

defmodule MyTestMacros do
  defmacro test_ok(method, url, params, schema, do: block) do
    quote do
      # 显式接收测试上下文,解构出setup定义的count变量
      test "#{unquote(method)} #{unquote(url)} 正常响应", %{count: count} do
        # 发送请求并获取response
        response = apply(Plug.Conn, unquote(method), [conn, unquote(url), unquote(params)])
        
        # 基础断言:状态码、Schema校验
        assert response.status == 200
        assert {:ok, data} = Jason.decode!(response.body)
        assert unquote(schema).changeset(data).valid?

        # 让block在当前测试函数作用域执行,可直接访问response和count
        unquote(block)
      end
    end
  end
end

关键调整点

  • 处理context传递:在生成的test块中显式添加%{count: count}参数,直接从setup注入的上下文中取出count变量,这样do:block就能直接访问。
  • 共享response变量:把do:block放在宏生成的测试函数内部,和response处于同一个作用域,此时unquote(block)会直接继承当前作用域的变量绑定,自然能识别response。

如果你的do:block需要更灵活的变量传递(比如不确定要用到哪些变量),也可以用Code.eval_quoted显式传递绑定:

# 宏内部的测试函数里替换unquote(block)为:
Code.eval_quoted(unquote(block), response: response, count: count, conn: conn)

内容的提问来源于stack exchange,提问作者Mou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:38:13