2014-02-28 15 views
7

我正在使用活動模型序列化器來呈現來自軌道控制器的JSON響應。Active Model Serializer,測試哪個序列化器用於呈現響應

我有這樣一個控制器的動作:

def show 
    @foo = Foo.find(params[:id]) 
    if @foo.user == current_user 
    render json: @foo, serializer: FooSerializer 
    else 
    render json: @foo, serializer: TrimmedFooSerializer 
    end 
end 

我希望能夠測試其串行已經在我的Rspec的控制器測試中被使用。是否有可能從測試中獲得對序列化程序的引用?

UPDATE:

我不認爲這是一個正確使用串行的。我現在在序列化程序本身有邏輯來有條件地包含屬性。控制器不應該關心使用哪個序列化器。

回答

3

你可以試試這個。我假設你正在使用factory_girl。您可以通過返回不同的用戶對current_user

describe "show" do 
    it "should use FooSerializer to serialize if the logged in user is the same as params user" do 
    user = FactoryGirl.create(:user) 
    controller.stub(:current_user).and_return(user) 
    FooSerializer.any_instance.should_receive(:to_json).and_return("{\"key\": \"value\"") 
    get :show, :id => user.id 
    response.should be_success 
    end 
end 
14

它已經有一段時間有人說,但萬一將來的Google找到這個寫其他的測試,我喜歡下面的方法:

RSpec::Matchers.define :serialize_object do |object| 
    match do |response| 
    @serializer_klass.new(object).to_json == response.body 
    end 

    chain :with do |serializer_klass| 
    @serializer_klass = serializer_klass 
    end 
end 

然後在測試中,你可以這樣做:

expect(response).to serialize_object(claim).with(ClaimSerializer) 

請注意,我沒有叫匹配「連載」,因爲早該已經定義了名稱的匹配。

+0

非常優雅的一個有用的aproach – Calin

1

進一步闡述Dan Draper's答案,我發現,使用JsonApi適配器時,這是要走的路:我把

RSpec::Matchers.define :serialize_resource do |object| 
    match do |response| 
    serialized_json(object) == response.body 
    end 

    chain :with do |serializer_klass| 
    @serializer_klass = serializer_klass 
    end 

    failure_message do |response| 
    "expected response body #{serialized_json(object)}, got #{response.body}" 
    end 

    def serialized_json(object) 
    serializer = @serializer_klass.new(object) 
    adapted = ActiveModelSerializers::Adapter::JsonApi.new(serializer) 
    adapted.serializable_hash.to_json 
    end 
end 
1

上面做了什麼Knightstick和改進一點點,例如像,錯誤消息並通過添加處理單個資源或資源集合的能力(我正在使用active_model_serializers gem,版本0.10.0)。

RSpec::Matchers.define :serialize_resource do |resource| 
    match do |response| 
    serialized_json(resource) == response.body 
    end 

    chain :with do |serializer_klass| 
    @serializer_klass = serializer_klass 
    end 

    failure_message do |response| 
    "expected response body #{serialized_json(resource).inspect}, got #{response.body.inspect}" 
    end 

    def serialized_json(resource) 
    options = if resource.is_a?(Array) 
       { each_serializer: @serializer_klass } 
       else 
       { serializer: @serializer_klass } 
       end 

    serializable = ActiveModelSerializers::SerializableResource.new(resource, options) 
    serializable.serializable_hash.to_json 
    end 
end 
相關問題