如何在长生不老药中模拟当前时间

How to mock current time in elixir

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

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

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

NB 这个答案自 Elixir v1.8 以来已废弃 现在默认参数不会在编译时求值。学分@HentikN.

Now the function will get current datetime and check for specific days [...]

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

就是说,你应该让这个函数接受一个参数 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() 不会工作,因为函数头在 编译时计算 。)

现在在你的测试中你可以调用这个函数来传递你想要的时间(这更重要)你的函数不是一个黑盒子,这取决于来自出门了。

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

define your own function/service MyDateTime.utc_now/0 and mock it in your tests. — Reference.