Как протестировать сильные параметры с помощью Rspec?

#ruby-on-rails #ruby #ruby-on-rails-4 #rspec #rspec-rails

#ruby-on-rails #ruby #ruby-on-rails-4 #rspec #rspec-rails

Вопрос:

Какова реальная стратегия тестирования фильтрации сильных параметров в контроллере Rails с помощью Rspec? (Кроме сопоставителей shoulda) Как написать неудачный тест, а затем сделать его зеленым?

Комментарии:

1. Помог ли мой ответ? Может быть, я могу что-то уточнить.

2. Спасибо, вы действительно помогли мне. Я не знал о with_indifferent_access . И как проверить требования к атрибутам, например, params.require :user?

Ответ №1:

Создайте 2 хэша с ожидаемыми и всеми (с неудовлетворительными) параметрами. Затем передайте все параметры в action и убедитесь, что ваша объектная модель получает только ожидаемые параметры. Этого не произойдет, если вы не используете строгие фильтры параметров. Затем добавьте разрешения к параметрам и снова проверьте test.

Например, это:

 # action
def create
  User.create(params)
end

# spec
it 'creates a user' do
  expect_any_instance_of(User).to receive(:create).
    with({name: 'Sideshow Bob'}.with_indifferent_access)
  post :create, user: 
    { first_name: 'Sideshow', last_name: 'Bob', name: 'Sideshow Bob' }
end
  

передаст все параметры пользователю, и тест завершится неудачей. И когда вы их фильтруете:

 def user_params
  params.require(:user).permit(:name)
end
  

и измените действие на User.create(user_params) , тест пройдет.

Комментарии:

1. create это метод уровня класса, определенный ActiveRecord::Base и унаследованный User . Таким образом, хотя expect_any_instance(User) (фиктивное ожидание для экземпляра User ) может работать, expect(User) (фиктивное ожидание для User класса) также будет работать и будет более минимальным.

Ответ №2:

Я лично использую shoulda-matcher от thoughtbot.

С помощью чего-то вроде:

 it do
  should permit(:first_name, :last_name, :email, :password).
    for(:update, params: params)
end
  

Ответ №3:

Вот как я это сделал:

   describe 'Safe Params' do

   let(:mixed_params) {
     {
       blueprint_application_environment: {
         id: 1000,
         blueprint_id:   1,
         application_id: 2,
         environment_id: 3
       },
       format: :json
     }
   }

context "when processing a Post request with a mix of permitted and unpermitted parameters" do
   before { post :create, mixed_params }

  it "a create will not set the value of the unpermitted parameter" do
     expect(JSON.parse(response.body)["id"]).not_to eq(1000)
   end

  it "a create will set the value of the permitted parameters" do
     expect(JSON.parse(response.body)["blueprint_id"]).to eq(1)
     expect(JSON.parse(response.body)["application_id"]).to eq(2)
     expect(JSON.parse(response.body)["environment_id"]).to eq(3)
   end
 end
  

конец

Код контроллера:

   def create
    @blueprint_application_environment = BlueprintApplicationEnvironment.new(blueprint_application_environment_params)
    if @blueprint_application_environment.save
      render 'show.json.jbuilder'
    else
      render json: @blueprint_application_environment.errors, status: :unprocessable_entity
    end
  end

def blueprint_application_environment_params
    params.require(:blueprint_application_environment).permit(:blueprint_id, :application_id, :environment_id)
end
  

Ответ №4:

как и при создании или обновлении объекта с использованием сильных параметров, он также похож, за исключением одной вещи, которую обычно вы делаете так:

сообщение: создать, book_id: @book.id

Но в сильном параметре вы должны сделать так:

сообщение: создать, {book_id: @book.id , комментарий: {идентификатор пользователя: 101, идентификатор книги: @book.id , описание: «стоит купить»}}

вы должны передать вложенные параметры.