【问题标题】:How to mock current time in elixir如何在长生不老药中模拟当前时间
【发布时间】:2019-03-19 00:25:13
【问题描述】:

我有一些测试取决于当前时间,但到目前为止我无法找到解决方案。我尝试了一些模拟库,例如mock,但它模拟了整个模块并且失败了。 任何帮助将不胜感激(如果我只模拟 DateTime.utc_now 一切都好)

注意:测试很大程度上依赖于其他 DateTimeDate 函数,因此模拟整个模块不是一个很好的选择(我也尝试过,但由于非常复杂的情况而失败,我在许多测试中都需要这个)

实际测试: 我有两个日期,start dateend date 作为我要测试的函数的输入。在为测试目的调用该函数之前,我插入了一些与当前周相关的数据(当前 dat 到接下来的 7 天)。现在该函数将获取当前日期时间并检查特定日期(每条记录将告诉它是否适用于一周中的当前日期以及正在迭代的当前时间段范围 -> 开始和结束日期)。 例如,一条记录申请mon -> 2:12 到 3:13

【问题讨论】:

  • 请提供需要模拟的测试用例。这个问题可能还有其他解决方案。
  • @denis.peplin 我已经添加了实际测试描述,希望对您有所帮助

标签: datetime testing elixir ecto


【解决方案1】:

NB 自 Elixir v1.8 起,此答案已过时 现在默认参数不会在编译时进行评估。致谢@HentikN。

现在该函数将获取当前 datetime 并检查特定日期 [...]

这是真正的问题所在。您无缘无故地使您的功能不纯。通常纯度意味着函数没有副作用,但盲目地根据外界改变结果也不是一种稳健的方法。

也就是说,你应该让这个函数接受一个参数now 或类似的参数(为简洁起见,它可能默认为now):

- def my_func(param) do
+ def my_func(param, dt \\ nil) do
+   dt = if is_nil(dt), do: DateTime.utc_now(), else: dt

(Naïve dt \\ DateTime.utc_now() 不起作用,因为函数头在编译时进行评估。)

现在在您的测试中,您可能会调用此函数来传递您想要的时间并且(更重要的是)您的函数不再是一个黑盒,这取决于来自外部的不相关条件。 p>

【讨论】:

  • 感谢@Aleksei 在这里提供了很好的选择,特别是让我知道function heads are evaluated at the compile time。但这次我会创建另一个函数并模拟它。参考:elixirforum.com/t/how-to-mock-current-time-in-elixir/17279/…
  • 是的,获取当前时间的提供者服务更好,我提出了最简单的解决方案。
  • @AlekseiMatiushkin 您是否有在编译时评估默认值的来源? elixir-lang.org/getting-started/… 说“任何表达式都可以用作默认值,但在函数定义期间不会对其进行评估。每次调用函数并且必须使用其任何默认值时,该默认值的表达式值将被评估”。
  • @HenrikN 我很确定发布此答案时发生了这种情况;现在它应该被认为已经过时了。我会自行更新答案。
【解决方案2】:

最适合我需要的解决方案(简单、效果好并且符合上述要求)是:

定义您自己的功能/服务MyDateTime.utc_now/0 并在您的测试中模拟它。 ——Reference.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多