mathew4509

mathew4509

Elixir test case to check if field is empty or invalid

Hi Elixir community, I am a newbie at Elixir and learning to write some effective tests for my blog application. My blog application has the following association:

Post → has_many comments
User → has_many comments
Comment → belongs to post and user
I would like to test

  1. if the post_id in my comment is available/empty and raise appropriate error
  2. if it(post_id) has invalid attribute and if yes, raise appropriate error

CODE:

lib>myapp>blog>comments>comment.ex

@required_field [
:comment_text, :string,
:post_id
]

schema

field :comment_text, :string,
belongs_to :post, Post
belongs_to :user, User

changeset

def changeset(comment, attrs) do
    comment
    |> foreign_key_constraint(:post_id)
    |> foreign_key_constraint(:user_id)
    |> cast(attrs, @required_field ++ @optional_field)
    |> validate_required(@required_field)
  end

I am using factories so no fixtures.

test>support>factory.ex

def comment_factory do
    %Comment{
      comment_text: "some comment_text",
      post: build(:post),
      user: build(:user)
    }
  end

test>myapp>blog>comments_test.exs

    @valid_attrs %{
      comment_text: "some comment text"
    }

Thanks in advance :smiley:

Most Liked

amnu3387

amnu3387

If I’m not mistaken, when you account for a foreign constraint on the changeset, |> foreign_key_constraint(:post_id) like you did the insertion if invalid will fail and the changeset will be marked as errored, so something like

assert {:error, Ecto.Changeset{}} = insert(:comment, @invalid_attrs)

should be what you’re looking for. If you want it to raise then you shouldn’t set the foreign constraint check, and leave it to the database to error, which will make ecto throw and exception.

But I think usually it’s preferable to have no exception and deal with {:ok, _}/{:error, _}.
If then wanted the caller can raise a specific one.

You can also check that the error is in the field you expect along with its message.
You would probably have some helper in your codebase for transforming errored changesets into a map of field => errors.

Ecto.Changeset.traverse_errors/2
With this you can build a simple helper:

def as_error_map(Ecto.Changeset{valid?: false} = changeset) do
  Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} ->
    Enum.reduce(opts, msg, fn {key, value}, acc ->
      String.replace(acc, "%{#{key}}", to_string(value))
    end)
  end)
end

And now you can use assert %{post_id: ["post doesn't exist"]} = as_error_map(changeset)

Where Next?

Popular in Questions Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement