2014-01-26 63 views
1

我想測試我的控制器只是調用服務對象的方法。我認爲一個測試間諜會是完美的。我究竟做錯了什麼?謝謝你的幫助!如何在控制器測試中使用簡單的測試間諜?

控制器:

class PostsController < ApplicationController 

    def create 
    @post = Post.new(post_params) 

    if @post.save 
     ServiceObject.new(@post).call 
     redirect_to posts_path, success: "#{@post.title} was successfully created." 
    else 
     render action: :new 
    end 
    end 

end 

服務對象:

class ServiceObject 

    def initialize(post) 
    @post = post 
    end 

    def call 
    puts "Service object was called!" 
    end 

end 

控制器測試:

require 'spec_helper' 

describe PostsController do 
    describe 'POST #create' do 
    it 'calls the service object' do 
     service_object = double(ServiceObject) 
     service_object.stub(:new).and_return(service_object) 
     service_object.stub(:call) 
     post :create, post: Fabricate.attributes_for(:post) 
     expect(service_object).to have_received(:call) 
    end 
    end 
end 

錯誤:

Failure/Error: expect(service_object).to have_received(:call) 
    (Double ServiceObject).call(any args) 
     expected: 1 time with any arguments 
     received: 0 times with any arguments 
+0

你檢查該職位被保存和'''如果@ post.save'''被返回true –

回答

1

試試這個:

require 'spec_helper' 

describe PostsController do 
    describe 'POST #create' do 
    let(:service_object) { double(:service_object) } 

    before do 
     ServiceObject.stub(:new).and_return(service_object) 
     service_object.stub(:call) 
    end 

    it 'calls the service object' do 
     post :create, post: Fabricate.attributes_for(:post) 

     expect(service_object).to have_received(:call) 
    end 
    end 
end 
+0

那麼這工作!我看到的主要區別在於我創建double的方式:「double(ServiceObject)」vs「double(:service_object)」。可能需要返回並重新訪問雙打。謝謝! –

+0

是的,這是正確的 - 這是關鍵的區別...這是創建一個模擬對象,由關鍵「':service_object'''確定......然後我們必須存根」'''''''''''''''''''' '''方法來返回模擬對象,我們依次在其上存根'''調用'',然後建立它接收到消息'''call'''的期望 –