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

如何在Elixir中实现类似Python requests-mock的特定API调用Mock

在Elixir中Mock外部API调用的实现方法

在Elixir里实现类似Python requests-mock的Mock功能,最常用也最规范的方式是用Mox——这是Elixir官方推荐的行为模拟库,它能帮你隔离外部依赖,让你在测试时完全控制被Mock模块的行为。下面我一步步给你演示怎么实现:

步骤1:添加Mox依赖

首先在你的mix.exs文件里的deps中加入Mox:

defp deps do
  [
    {:mox, "~> 1.0", only: :test}
  ]
end

然后运行mix deps.get安装依赖。

步骤2:定义API行为(Behaviour)

为了让Mock能和真实模块保持一致的调用接口,我们需要先给API模块定义一个行为(类似Python里的抽象基类):

defmodule APIBehaviour do
  @callback make_call() :: any()
end

然后让你的真实API模块实现这个行为:

defmodule API do
  @behaviour APIBehaviour

  def make_call do
    # 这里是真实的外部API调用逻辑,比如用HTTPoison或者Tesla
    # 示例:
    # HTTPoison.get!("https://external-api.example.com")
  end
end

步骤3:改造业务代码支持依赖注入

为了让测试时能替换真实的API模块,我们需要在Item模块里通过应用配置来注入API实现,而不是直接硬编码调用:

defmodule Item do
  # 默认使用真实的API模块,测试时可以替换为Mock
  @api Application.compile_env(:your_app_name, :api_module, API)

  def build_request do
    # 调用注入的API模块的make_call方法
    api_response = @api.make_call()
    # 这里是你原本的业务逻辑,基于API响应构建请求
    # ...
  end
end

注意把:your_app_name替换成你实际的应用名称。

步骤4:编写测试用例Mock API调用

首先在test/test_helper.exs里定义Mock模块,绑定到我们之前定义的行为:

Mox.defmock(APIMock, for: APIBehaviour)

然后在Item的测试文件里,就可以像Python的with语句一样,临时Mock API的调用了:

defmodule ItemTest do
  use ExUnit.Case, async: true
  import Mox

  # 确保每个测试结束后验证Mock的调用是否符合预期
  setup :verify_on_exit!

  test "build_request正确使用API的返回值构建请求" do
    # 设置Mock的预期:当调用APIMock.make_call时,返回我们指定的模拟数据
    expect(APIMock, :make_call, fn -> "mocked_api_response_data" end)

    # 临时替换应用配置,让Item模块使用Mock代替真实API
    Application.put_env(:your_app_name, :api_module, APIMock)

    # 调用要测试的函数
    result = Item.build_request()

    # 验证结果是否符合预期
    assert result == "expected_built_request" # 替换成你的实际预期值
  end
end

补充:用meck快速Mock(适合简单场景)

如果你只是想快速Mock某个模块的函数,不想定义行为,也可以用Erlang的meck库(Mox底层也是基于它的)。比如:

defmodule ItemTest do
  use ExUnit.Case, async: true

  test "build_request使用Mock的API调用" do
    # 启动Mock,替换API模块的make_call函数
    meck.new(API, [:non_strict])
    meck.expect(API, :make_call, fn -> "mocked_data" end)

    # 测试逻辑
    result = Item.build_request()
    assert result == "expected_result"

    # 清理Mock
    meck.unload(API)
  end
end

不过这种方式没有行为约束,长期维护的话还是推荐用Mox,更符合Elixir的设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:30:39