6

Tôi có một số before_filter trên lớp học ApplicationController và tôi muốn viết bài kiểm tra cho nó? Tôi nên viết bài kiểm tra này ở đâu? Tôi không muốn đi vào mọi tệp kiểm tra của lớp con và lặp lại bài kiểm tra về bộ lọc này.Làm thế nào để kiểm tra bộ điều khiển ứng dụng trước khi các phương pháp lọc trong Rails 3?

Do đó, cách được đề xuất để kiểm tra ApplicationController before_filters là gì?

Lưu ý rằng tôi đang sử dụng Rails 3.2.1 với minitest.

Trả lời

5

Trường hợp của tôi hơi khác với trường hợp của bạn, nhưng tôi cần thực hiện một việc tương tự như xác thực kiểm tra trên trang web (với Devise). Dưới đây là cách tôi đã thực hiện:

# 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 

Nếu có bộ điều khiển cụ thể cần bỏ qua bộ lọc trước, tôi sẽ kiểm tra để đảm bảo chúng bỏ qua kiểm tra của bộ điều khiển cụ thể. Đây không phải là hoàn cảnh của bạn vì tôi quan tâm đến hiệu quả của phương pháp, không chỉ biết rằng nó được gọi, nhưng tôi nghĩ tôi sẽ chia sẻ trong trường hợp bạn thấy nó hữu ích.

0

Thông thường khi tôi muốn một cái gì đó như thế này tôi chỉ kiểm tra hành vi mong đợi mà không tính đến hành vi cụ thể này có thể được thực hiện trong bộ lọc chứ không phải trong phương thức. Vì vậy, đối với kịch bản đơn giản sau đây:

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 

Tôi sẽ thử nghiệm đơn giản rằng #show và #edit gán điều @resource. Điều này làm việc cho các kịch bản đơn giản khá nhiều ok. Nếu bộ lọc được áp dụng cho rất nhiều hành động/bộ điều khiển thì bạn có thể trích xuất mã thử nghiệm và sử dụng lại nó trong số các thử nghiệm.

+0

Nếu bộ lọc là trên một bộ điều khiển cụ thể, tôi đồng ý với cách tiếp cận của bạn. Bộ lọc của tôi được khai báo trên lớp 'ApplicationController' (và được kế thừa cho tất cả các bộ điều khiển xuất phát từ nó). Phương pháp lọc mà tôi sử dụng phải thực hiện với các kiểm tra theo yêu cầu. Tôi cần phải viết một bài kiểm tra ở một nơi mà tôi có thể sử dụng các phương pháp như những người (hoặc tương đương?) Tôi sử dụng khi thử nghiệm một bộ điều khiển cụ thể. Có lẽ câu trả lời của bạn cho vấn đề của tôi là trong cụm từ cuối cùng của bạn ("Nếu bộ lọc ... trong số các bài kiểm tra"), nhưng tôi không thể thấy điều đó. Ngoài ra, làm thế nào để kiểm tra xem phương thức được gắn vào 'before_filter' có thực sự gắn liền với nó không? –

+1

Bạn có thể viết một bộ thử nghiệm được bao gồm trong mọi kiểm tra bộ điều khiển và chạy cho mọi hành động. Điều này nên được đơn giản (r) để làm bằng cách sử dụng RSpec bằng cách sử dụng 'it_behaves_like' (https: // www.relishapp.com/rspec/rspec-core/v/2-0/docs/example-groups/shared-example-group), nhưng trên Test đơn giản :: Đơn vị bạn có thể làm những thứ như vậy. Có thể bạn có thể lấy cảm hứng từ ActiveModel :: Lint: Bài kiểm tra (http://api.rubyonrails.org/classes/ActiveModel/Lint/Tests.html - https://github.com/rails/rails/blob/master/activemodel /lib/active_model/lint.rb) –

1

Tôi bây giờ tin rằng tôi phải có tất cả các kiểm tra bộ điều khiển của tôi kiểm tra về sự tồn tại before_filter và bộ lọc này hoạt động như mong đợi. Điều này là bởi vì, tôi không thể biết liệu một bộ điều khiển sử dụng một skip_before_filter khi nó không nên.

Do đó, tôi quyết định sử dụng mock (@controller.expects(:before_filter_method)) để đảm bảo rằng bộ lọc được gọi. Vì vậy, ví dụ, trong một hành động index tôi viết trong thử nghiệm của tôi:

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

Điều này sẽ đảm bảo rằng bộ điều khiển của tôi gọi before_filter_method trên các hành động cụ thể. Tôi phải làm điều này trên tất cả các thử nghiệm hành động của mình.

Nếu bất kỳ ai khác có giải pháp tốt hơn, hãy cho tôi biết.

+0

Tại sao bạn không chỉ cần kiểm tra xem điều gì sẽ xảy ra có hoặc không có bộ lọc đó? Bằng cách này, bạn được tách ra khỏi bộ lọc và chỉ quan tâm * những gì * xảy ra nếu bộ lọc được gọi, không cho dù nó được gọi hay không. Lợi ích bổ sung của việc này là bạn có thể đổi tên bộ lọc, thay đổi phạm vi của nó, di chuyển nó sang một số lớp khác hoặc thay thế hoàn toàn nó bằng người quan sát, dịch vụ hoặc bạn có gì. –

2

Cải thiện câu trả lời @bmaddy, bạn cần phải thiết lập định tuyến để các thông số kỹ thuật chạy.

Đây là một đường ray 5 ví dụ làm việc:

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 
Các vấn đề liên quan