mocking - Viaje en el tiempo y tiempo de congelación en Elixir
erlang (1)
Al escribir pruebas de integración que dependen de la fecha / hora actual, es muy útil poder freeze
o travel
a un momento específico (por ejemplo, timecop para ruby)
¿Hay alguna manera de lograr algo similar en Elixir / Erlang?
Intenté burlar las funciones integradas de Erlang :os.timestamp
:erlang.universaltime
usando la biblioteca de meck
, pero falla con :cannot_mock_builtin
.
En principio, podría implementar mi propia biblioteca de utilidades que permitiría burlar fácilmente la hora actual y luego usarla en todas partes en lugar de usar métodos integrados; sin embargo, algunas bibliotecas usan integradas, por lo que esta no es una opción viable (por ejemplo, Ecto.Model.Timestamps
, generando valores inserted_at
y updated_at
)
Elixir
Sugeriría que implemente esto a través de la inyección de dependencia. Por ejemplo (usando la nueva API de tiempo en Erlang 18):
defmodule Thing do
def do_stuff(data), do: do_stuff(data, &:erlang.system_time/0)
def do_stuff(data, time), do: {data, time.()}
end
En sus pruebas, puede reemplazar fácilmente el código de tiempo:
defmodule ThingTest do
use ExUnit.Case
test "the time" do
assert do_stuff("data", fn -> 123 end) == {"data", 123}
end
end
Erlang
Aquí está la forma correspondiente de hacer esto en 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()}.
Y la prueba:
-module(thing_tests).
-include_lib("eunit/include/eunit.hrl").
do_stuff_test() ->
?assertEqual({"data", 123}, do_stuff("data", fun() -> 123 end).