Rafael Costa
Rafael Costa

Reputation: 1481

Can't test controller render due to ActiveRecord::StatementInvalid:error

Ok, I have this controller code:

def create
    @foo = Foo.new(user: User.new(user_params))
    if @foo.save
      redirect_to foos_path
    else
      render :new
    end
end

And I would like to test if it re-renders the new page when the user email is invalid. To do that, I created this test:

it "should re-render the new template" do
    post :create, params: { user: attributes_for(:user, email: "abc.com") } }
    expect(response).to render_template(:new)
end

However, the test is failing due to this error:

 Failure/Error: if @foo.save

 ActiveRecord::StatementInvalid:
   PG::NotNullViolation: ERROR:  null value in column "user_id" violates not-null constraint
   DETAIL:  Failing row contains (260, null).
   : INSERT INTO "foos" DEFAULT VALUES RETURNING "id"

The Foo table has a

t.belongs_to :user, null: false, index: true

so that it does not add a foo without a user.

I think this error is actually a desired behavior, since it prevents the foo to be saved without a user and the user cant be saved with an invalid email. But I still need to test it, so am I testing it wrongly? How can I do that? Is there something missed?

Thanks in advance!

Upvotes: 0

Views: 142

Answers (2)

Thanh
Thanh

Reputation: 8604

You can try:

@foo = Foo.new
@foo.build_user(user_params)
@foo.save

It should save both user and foo.

This will create a transaction so that it will not save any records to database until foo and user are validated.

Upvotes: 0

Fallenhero
Fallenhero

Reputation: 1583

Your question is not very clear, but I guess here is the error:

@foo = Foo.new(user: User.new(user_params))

User.new will not save the User to DB, so you will not have an ID and will fail your user_id non-null constraint.

Use:

user = User.create(user_params)
@foo = Foo.new(user: user)

instead

Upvotes: 1

Related Questions