Ruby on Rails 2.3.8: поведение freaking destroy игнорируется перед фильтром - PullRequest
1 голос
/ 13 июля 2011

Итак, я возился с тестированием прав пользователя в моем приложении, но этот тест действительно странный. Вот фильтр до, который я пытаюсь заставить работать в моем ContentsController:

  before_filter :only => :destroy do |controller| 
    controller.prevent_packet_sniffing_destroy_hack(controller_name.classify.constantize)
  end

Я работаю над тем, чтобы заставить работать только набор тестов этого одного контроллера, чтобы я мог скопировать фильтр before на другие контроллеры с аналогичным поведением

Тест:

 should "not allow the deleting of #{plural_name} on different accounts" do
      login_as(@user)
      p = Factory(factory_name, :account => Factory(:account))

   assert_difference("#{klass}.count", 0) do
    delete :destroy, :id => p.id
    klass.find_by_id(p.id).should_not be_nil
  end
    end

для тех, кто заинтересован, это обобщенный тест, который я запускаю для всех объектов с похожей функциональностью Вот переменная, определенная параметром метода, 'klass'

  factory_name = klass.name.tableize.singularize.to_sym
  plural_name = klass.name.tableize
  singular_name = klass.name.tableize.singularize

метод уничтожения контроллера, который я пытаюсь проверить:

 def destroy
    @content = Content.find(params[:id])

    if not has_permission_to_change?(@content)      
      flash[:error] = 'You do not have permission to delete this content.'
    else
      @content.destroy
    end

    respond_to do |format|
      format.html { redirect_to(contents_url) }
    end
  end

Два метода, которые выполняют проверку разрешений:

  def prevent_packet_sniffing_destroy_hack(klass)
    if not has_permission_to_change?(klass.find(params[:id]))
      puts "should be denying access"
     # render :template => "/error/401.html.erb", :status => 401
     return false
    end
  end

  def has_permission_to_change?(object)
    if (current_user.is_standard? and object.user_id != current_user.id) or
       object.account_id != current_account.id
       return false
    else
       return true
    end
  end

и, наконец, вывод консоли

Loaded suite test/functional/contents_controller_test
Started
...should be denying access
E........
Finished in 1.068664 seconds.

  1) Error:
test: destroy contents! should not allow the deleting of contents on different accounts. (ContentsControllerTest):
RuntimeError: This content should not be allowed to be deleted

Вы заметите, что в середине тестов тот, кто не печатает, "должен отказывать в доступе", как в путах в моем фильтре before.

Я также поместил оператор put прямо над ошибкой флэш-памяти, где говорится, что «у вас нет разрешения на удаление этого содержимого», и это печатается.

* Примечание: функциональность корректно работает в режиме разработки, когда фактически тестируется с помощью веб-браузера и перехватчика пакетов.

Любая помощь очень ценится.

1 Ответ

0 голосов
/ 14 июля 2011

Просто перечитайте свой тест:

begin
  delete :destroy, :id => p.id
  raise "This #{singular_name} should not be allowed to be deleted"
rescue ActiveRecord::RecordNotFound
  assert true
end

Что вы проверяете, так это то, что действие destroy идет хорошо. И это всегда так (если нет Content с id, который вы проходите, но как это могло произойти?).

Вы на самом деле не проверяете, уничтожен объект или нет.

Вы должны переписать это так:

should "not allow the deleting of #{plural_name} on different accounts" do
  login_as(@user)
  p = Factory(factory_name, :account => Factory(:account))
  delete :destroy, :id => p.id
  klass.name.find_by_id(p.id).should be_nil
end

Обратите внимание, что здесь вам не хватает юнит-тестов, и вы должны более изолировать ваши сценарии использования, используя заглушки.

...