首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟Mox库错误:模块Myapp.MyModule不是行为,请将行为传递给:for

模拟Mox库错误:模块Myapp.MyModule不是行为,请将行为传递给:for
EN

Stack Overflow用户
提问于 2018-01-26 19:39:25
回答 2查看 1.3K关注 0票数 5

我正试图在我的药剂项目中使用名为Mox的模拟库,但即使是下面的正式文档:https://hexdocs.pm/mox/Mox.html

我不能为我的模块函数定义新的行为。在尝试运行测试时,它会给出以下错误:

** (ArgumentError)模块Myapp.MyModule不是一种行为,请将行为传递给:for (mox) lib/mox.ex:210: Mox.validate_behaviour!/1 (mox) lib/mox.ex:198: Mox.defmok/2(长生不老药) lib/code.ex:376: code.requfile/2 (elixir) lib/enum.ex:678: Enum.“-各/2-列出^foreach/1-0-”/2 (elixir) /enum.ex:678: Enum.each/2

到目前为止,我尝试过的是:

test_helper.exs:

代码语言:javascript
复制
ExUnit.start()
Mox.defmock(Myapp.MockMyModule, for: Myapp.MyModule)

MyModuleTest.exs

代码语言:javascript
复制
defmodule MyModuleTest do
    use ExUnit.Case

    import Mox

    setup :verify_on_exit!

    test "Test status processor in transit with mocked result" do

        Myapp.MyModule
        |> expect (:put_calculated_eta, fn body, shipment_id, authorization_key -> {:ok, "bla", 200} end)

        map = #Some data that fits the function interface

        assert {:ok, "bla", 200} == Myapp.MyModule.update_shipment_eta(map)
    end
end

我认为最奇怪的是,在文档中,它确实期望模块被传递为模拟,但在错误中它请求行为(我猜应该是函数,我已经尝试过了,但没有成功.有人能告诉我为什么我的模块不能被嘲笑吗?

为了澄清这一点,这个嘲弄是为了外部api的响应。

如果我没有提供足够的信息,请告诉我。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-27 12:20:46

正如错误信息所传达的,缺少的是一种行为。长生不老行为(注意英式拼写)类似于强类型OOP语言中的“接口”;也就是说,它们描述了其他模块实现的一组功能。

例如,此模块使用单个回调方法do_work/1定义行为,该方法期望一个整数形式的作业,并返回{:ok, result}{:error, reason}

代码语言:javascript
复制
defmodule WorkBehavior do
  @callback do_work(job::integer) :: {:ok, integer} | {:error, atom}
end

这些模块实现了这种行为:

代码语言:javascript
复制
defmodule LazyWorker do
  @behaviour WorkBehavior  
  @impl WorkBehavior
  def do_work(job), do: {:error, :too_tired}
end

defmodule HardWorker do
  @behaviour WorkBehavior
  @impl WorkBehavior
  def do_work(job), do: {:ok, job + 42}
end

行为的最终目标是允许您编写模块化代码,可以轻松地交换各种实现。使用上面的代码,可以将worker模块作为参数传递,而不是硬编码它。比较:

代码语言:javascript
复制
def closely_coupled do
  HardWorker.do_work(12)
end

代码语言:javascript
复制
def loosely_coupled(worker) do
  worker.do_work(12)
end

Mox要求您做的是定义一个捕捉MyApp.MyModule API的行为,这样Mox就可以创建一个可供您测试的假版本。这种方法的动机,相对于更典型的动态模拟,由JoséValim在这个职位中解释。

如果没有看到MyApp.MyModule的代码,我就无法确切地告诉您要编写什么代码,但是通常,您应该为每个您想要模拟的方法添加@callback标记。有关类型选择和行为的介绍,请参见此页 (提示:@callback标记使用类型选择语法,因此请阅读整个页面)。

票数 8
EN

Stack Overflow用户

发布于 2019-10-10 15:10:43

您需要定义Myapp.MyModule模块的行为。

如果您不想编写单独的模块来描述https://stackoverflow.com/a/48475734/438990中所建议的行为,那么您可以为您的公共功能添加@回调描述符。

代码语言:javascript
复制
defmodule Myapp.MyModule
  @callback put_calculated_eta(String.t()) :: String.t()
  def put_calculated_eta(fiz)
    fiz + "buz"
  end
end

然后,您可以注册模拟与

代码语言:javascript
复制
Mox.defmock(Myapp.MockMyModule, for: Myapp.MyModule)

而不是

代码语言:javascript
复制
Mox.defmock(Myapp.MockMyModule, for: Myapp.MyModuleBehavior)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48468416

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档