我正试图在我的药剂项目中使用名为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:
ExUnit.start()
Mox.defmock(Myapp.MockMyModule, for: Myapp.MyModule)MyModuleTest.exs
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的响应。
如果我没有提供足够的信息,请告诉我。
发布于 2018-01-27 12:20:46
正如错误信息所传达的,缺少的是一种行为。长生不老行为(注意英式拼写)类似于强类型OOP语言中的“接口”;也就是说,它们描述了其他模块实现的一组功能。
例如,此模块使用单个回调方法do_work/1定义行为,该方法期望一个整数形式的作业,并返回{:ok, result}或{:error, reason}。
defmodule WorkBehavior do
@callback do_work(job::integer) :: {:ok, integer} | {:error, atom}
end这些模块实现了这种行为:
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模块作为参数传递,而不是硬编码它。比较:
def closely_coupled do
HardWorker.do_work(12)
end与
def loosely_coupled(worker) do
worker.do_work(12)
endMox要求您做的是定义一个捕捉MyApp.MyModule API的行为,这样Mox就可以创建一个可供您测试的假版本。这种方法的动机,相对于更典型的动态模拟,由JoséValim在这个职位中解释。
如果没有看到MyApp.MyModule的代码,我就无法确切地告诉您要编写什么代码,但是通常,您应该为每个您想要模拟的方法添加@callback标记。有关类型选择和行为的介绍,请参见此页 (提示:@callback标记使用类型选择语法,因此请阅读整个页面)。
发布于 2019-10-10 15:10:43
您需要定义Myapp.MyModule模块的行为。
如果您不想编写单独的模块来描述https://stackoverflow.com/a/48475734/438990中所建议的行为,那么您可以为您的公共功能添加@回调描述符。
defmodule Myapp.MyModule
@callback put_calculated_eta(String.t()) :: String.t()
def put_calculated_eta(fiz)
fiz + "buz"
end
end然后,您可以注册模拟与
Mox.defmock(Myapp.MockMyModule, for: Myapp.MyModule)而不是
Mox.defmock(Myapp.MockMyModule, for: Myapp.MyModuleBehavior)https://stackoverflow.com/questions/48468416
复制相似问题