Как проверить контроллер приложения перед фильтрацией методов в Rails 3? - PullRequest
6 голосов
/ 17 марта 2012

У меня before_filter в моем ApplicationController классе, и я хочу написать тест для него? Где я должен написать этот тест? Я не хочу заходить в каждый тестовый файл контроллера подкласса и повторять тест об этом фильтре.

Следовательно, каков рекомендуемый способ проверки ApplicationController before_filters?

Обратите внимание, что я использую Rails 3.2.1 с minitest.

Ответы [ 4 ]

7 голосов
/ 14 апреля 2012

Мой случай немного отличается от вашего, но мне нужно было сделать что-то похожее на тестирование аутентификации на сайте (с Devise). Вот как я это сделал:

# application_controller.rb
class ApplicationController < ActionController::Base
  before_filter :authenticate_user!
end

# application_controller_test.rb
require 'test_helper'

class TestableController < ApplicationController
  def show
    render :text => 'rendered content here', :status => 200
  end
end

class ApplicationControllerTest < ActionController::TestCase
  tests TestableController

  context "anonymous user" do
    setup do
      get :show
    end
    should redirect_to '/users/sign_in'
  end
end

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

2 голосов
/ 29 марта 2016

Улучшение ответа @bmaddy, вам нужно настроить маршрутизацию для запуска спецификаций.

Вот пример работы с rails 5:

require 'test_helper'

class BaseController < ApplicationController
  def index
    render nothing: true
  end
end

class BaseControllerTest  < ActionDispatch::IntegrationTest
  test 'redirects if user is not logedin' do
    Rails.application.routes.draw do
      get 'base' => 'base#index'
    end

    get '/base'

    assert_equal 302, status
    assert_redirected_to 'http://somewhere.com'
    Rails.application.routes_reloader.reload!
  end

  test 'returns success if user is loggedin' do
    Rails.application.routes.draw do
      get 'base' => 'base#index'
    end

    mock_auth!

    get '/base'
    assert_equal 200, status
    Rails.application.routes_reloader.reload!
  end
end
1 голос
/ 22 марта 2012

Теперь я считаю, что мне нужно проверить все мои тесты контроллеров на предмет существования before_filter и что этот фильтр работает как положено. Это потому, что я не могу знать, использует ли контроллер skip_before_filter, когда он не должен.

Поэтому я решил использовать mock (@controller.expects(:before_filter_method)), чтобы убедиться, что фильтр вызван. Так, например, в действии index я пишу в своем тесте:

test "get index calls the before filter method" do
  @controller.expects(:before_filter_method)
  # fire
  get :index      
end

Это позволит убедиться, что мой контроллер вызывает before_filter_method для конкретного действия. Я должен сделать это на всех моих тестах действий.

Если у кого-то есть лучшее решение, дайте мне знать.

0 голосов
/ 17 марта 2012

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

class Controller < ApplicationController
  before_filter :load_resource, :only => [:show, :edit]

  def show
  end

  def edit
  end

  def index
  end

  #########
  protected 
  #########

  def load_resource
    @resource = Model.find(params[:id])
  end
end

Я бы просто протестировал, чтобы #show и #edit назначали @resource.Это работает для простых сценариев в значительной степени хорошо.Если фильтр применяется ко многим действиям / контроллерам, вы можете извлечь код тестирования и повторно использовать его среди тестов.

...