2
votes

I am new to Rails and I want to test my set strong parameters of the Book model with a controller test. I am using Minitest and Rails 4.

Book model:

class Book < ActiveRecord::Base
  validates :title, presence: true, length: { in: 1..150 }
end

Book controller wit params:

def create
  @book = Book.new book_params

  if @book.save
    redirect_to action: "index", notice: 'Success.'
  else
    render :new
  end
end

private
  def book_params
    params.require(:book).permit(:title, :cover_image)
  end

My idea for a test - does fail, because it creates an entry:

assert_no_difference('Book.count') do
  post :create, book: {
    id: 123,
    title: "Lorem ipsum"
  }
end

How can I get the tests go green and is it correct to test the strong parameters with a controller test?

2
Why wouldn't it create an entry?j-dexx
My thought was, that it shouldn't create a record because of the given id parameter. Or does Rails - just thinking out loud - dismiss all parameters not whitelisted and that's why my test is creating an entry?lorem monkey
Unpermitted parameters will just be dropped.eugen
Oook. Thank you for the insight :) I answered the question myself - hope it will help someone else new into Rails.lorem monkey

2 Answers

3
votes

I am looking for an answer to almost the same question. When using Rails 5 I eventually came up with a solution (call it workaround if you like :-) for testing that the unwanted params don't actually get through. In my (simplified here) case I want to disallow some "security critical" params being passed through when creating a new user.

In the controller (permitting only email and password):

    private
        def user_params
            params.require(:user).permit(:email, :password)
        end

In the integration test:

test "not permitted signup data submitted" do
    new_user_email = "tester_" + (0...10).map { ('0'..'9').to_a[rand(26)] }.join + "@testing.net"
    get signup_path
    assert_difference 'User.count', 1 do
        post signup_path, params: { user: { email: new_user_email, password: "testpassword", role_id: 1 } }
    end
    user = User.last
    assert user.email == new_user_email
    assert user.role_id == nil
end

Here I submit an additional, "sensitive" parameter role_id with the value of 1 (admin). I expect the user to be created. Then I read that newly (last) created user and expect it to have role_id empty (nil). To make the test fail I add :role_id to user_params. Removing it, makes the test pass. Obviously if your attribute can't be nil (aka NULL in SQL), you can test for default value being stored instead of the submitted one.

2
votes

Since Rails drops all unpermitted parameters not in permit, the new record will be created, hence the test will be red.

Although, one can raise an exception with the action_on_unpermitted_parameters method when non-whitlisted parameters are submitted.