简体   繁体   中英

Testing Elixir/Ecto dates

I have yet another problem with testing in Elixir and Phoenix. I have a module which represents users which looks like so:

defmodule AppExample.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias SecuritytrailsApi.Accounts.User

  schema "users" do
    field :email, :string
    field :password, :string, virtual: true
    field :password_hash, :string
    field :last_login, :naive_datetime

    timestamps()
  end

  ...
  def registration_changeset(%User{} = user, attrs \\ %{}) do
    user
    |> changeset(attrs) # validating and castnig email
    |> validate_required([:password])
    |> put_password_hash # creates password hash from password
    |> set_default_date
  end

  defp set_default_date(chanegset) do
     case changeset do
       %Ecto.Changeset{valid?: true} ->
          put_change(changeset, :last_login, Ecto.DateTime.utc)
       _ -> changeset
     end
  end
end

And let's say I have an Accounts context which is responsible for creating new accounts. Like so:

defmodule AppExample.Accounts do
  def create_user(attrs \\ %{}) do
    %User{}
    |> User.registration_changeset(attrs)
    |> Repo.insert
  end
end

So as you can ese, the field last_login is inserted automatically using Ecto.DateTime.utc to get the now() time. So, my questions are the following:

1) Is this the correct way of adding a default now() value to a field in Ecto?

2) How can I write tests for this? I don't know how can I get the value of that particular field. Please check the example below for details.

defmodule AccountsTest do
   @valid_attrs %{email: "mail@mail.com", password: "123123"}
   test "create_user/1 creates a new users with last_login set to now" do
     assert {:ok, %User{} = user} = Accounts.create_user(@valid_attrs)
     assert user.email == "mail@mail.com"
     assert user.last_login == ### ????? How can I get that NOW value here for the test
   end
end

1) Is this the correct way of adding a default now() value to a field in Ecto?

You can default this field to now() in a migration instead of computing its value manually.

alter table(:users) do
  modify :last_login, :string, default: fragment("now()")
end

2) How can I write tests for this?

You could assert that the value is in the last eg 15 seconds:

assert DateTime.diff(DateTime.utc_now, user.last_login, :second) <= 15

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM