【问题标题】:Time travel and time freezing in ElixirElixir 中的时间旅行和时间冻结
【发布时间】:2015-12-30 11:08:36
【问题描述】:

在编写依赖于当前日期/时间的集成测试时,能够freezetravel 到特定时刻非常方便(例如timecop 用于ruby)

有没有办法在 Elixir/Erlang 中实现类似的功能?

我尝试使用meck 库模拟Erlang 内置插件:os.timestamp:erlang.universaltime,但使用:cannot_mock_builtin 失败。

原则上,我可以实现自己的实用程序库,而不是轻松模拟当前时间,然后在任何地方使用它而不是内置方法;但是,一些库使用内置函数,因此这不是一个可行的选项(例如 Ecto.Model.Timestamps,生成 inserted_atupdated_at 值)

【问题讨论】:

  • 你检查过 Erlang 18 最近的更新日志吗?它具有 TImeWarp 功能,并且 ferd 在 learnyousomeerlang 中对此进行了介绍。 Erlang time warp documentationferd writings on the subject。不确定他们是否回答了您的问题...
  • @Olinasc 时间扭曲功能通常只与对更改系统时间和时钟的反应有关,它不允许您仅更改测试时间。

标签: mocking erlang elixir


【解决方案1】:

灵药

我建议您通过依赖注入来实现这一点。例如(使用 Erlang 18 中的新时间 API):

defmodule Thing do
  def do_stuff(data), do: do_stuff(data, &:erlang.system_time/0)
  def do_stuff(data, time), do: {data, time.()}
end

在您的测试中,您可以轻松替换时间码:

defmodule ThingTest do
  use ExUnit.Case

  test "the time" do
    assert do_stuff("data", fn -> 123 end) == {"data", 123}
  end
end

二郎

以下是在 Erlang 中执行此操作的相应方法:

-module(thing).
-export([do_stuff/1, do_stuff/2]).

do_stuff(Data) -> do_stuff(Data, fun erlang:system_time/0).

do_stuff(Data, Time) -> {Data, Time()}.

还有测试:

-module(thing_tests).
-include_lib("eunit/include/eunit.hrl").

do_stuff_test() ->
    ?assertEqual({"data", 123}, do_stuff("data", fun() -> 123 end).

【讨论】:

  • 感谢您的回答!但是我不确定这种方法在集成测试的上下文中如何工作,其中 external 库使用erlang:system_time(例如Ecto 用于在插入/更新的行上自动设置时间戳)...跨度>
  • 是的,你没有运气。没有办法解决这个问题,除非这些库能够参数化时间。我想你唯一的选择是在虚拟机中运行系统并在 Erlang 之外修改时间。
  • 感谢您提供的信息 - 我假设可能是这种情况...我会保留一段时间的问题,看看是否有人提出替代解决方案...
  • @jesenko,好吧,无论如何你都可以像这样archive09.linux.com/feature/147801 假装整个光束的时间
  • 对于集成测试,您可以创建一个具有测试中所需状态的生成服务器,本文展示了如何为 API 执行此操作。 blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts
猜你喜欢
  • 1970-01-01
  • 2023-02-20
  • 2021-09-01
  • 2017-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
相关资源
最近更新 更多