2011-09-28 52 views
0

我正在使用Ruby on Rails 3.1.0和rspec-rails 2 gem。我正在測試我的控制器代碼(順便說一下:我是新手rspec),我想使一個類對象實例返回一個預定義的值。也就是說,在我的控制,我有:如何使類對象實例返回預定義的值?

def create 
    ... 

    if @current_user.has_authorization? 
    ... 
    else 
    ... 
    end 
end 

爲了測試if聲明我想提出可能是(對我的工作對當前規範例如「else部分」 - 請閱讀下面作爲示例實現),@current_user.has_authorization?返回false

我該怎麼做?


我想在我的規範文件中的以下,但似乎沒有達到預期效果:

it "should have no authorization" do 
    @current_user.stub(:has_authorization?).and_return(false) 

    # I also tried the following and it still doesn't work 
    # @current_user.should_receive(:has_authorization?).and_return(false) 

    post :create 
    ... 
end 
+0

如果您在'@ current_user.stub ...'調用之後添加'@current_user.has_authorization?.should be_false',會發生什麼? – Fabio

+0

@Fabio - 恰巧測試通過了。當然,我註釋了'post:create ...'代碼以使其工作。 – user502052

+0

所以這個問題不在存根調用中,它應該在別的地方,也許你稍後在代碼中改變'@ current_user'的值。爲了避免這種問題,我使用mocha作爲嘲笑框架,它定義了一個名爲'any_instance'的方法,爲該類的所有實例存根方法。如果你有興趣,我可以發佈作爲答案(它太長,作爲評論)。 – Fabio

回答

1

在RSpec的測試環境中@current_user是不一樣的@current_user在上下文你的控制器。一個是實例變量,Rails正在運行的控制器類的實例中。另一個是你的rspec測試中的一個實例變量。

你不應該捅你的用戶變量,而是需要讓它變成Rails找到由測試框架提供的用戶。看看this example

0

爲了避免這個問題,你可以使用mocha,要做到這一點做到以下幾點:

摩卡寶石添加到您的Gemfile和運行bundle install

然後改變Rspec的模擬配置框架在spec_helper.rb文件

RSpec.configure do |config| 
    config.mock_with :mocha 
    # config.mock_with :rspec 
end 

然後在你的天賦,你可以做到這一點

it "should have no authorization" do 
    User.any_instance.stubs(:has_authorization?).returns(false) 
    post :create 
    ... 
end 

本(或the correct answer from Coderer)將解決您的問題。

請注意,據我所知在Rspec嘲諷函數中沒有any_instance等價物。

0

當你的規範運行,self指向一個測試對象(有時嘗試一個規範內部p selfputs self.class,看看自己),所以@current_user指的是該測試對象的實例變量。它與控制器上的@current_user實例變量沒有任何關係。

一種方式做你想要的是你的控制器上創建CURRENT_USER 方法訪問,並調用它,而不是直接訪問@current_user的。然後,您可以根據您的規範對該方法進行存根或模擬,假設您可以獲取指向您的控制器實例的指針。

另一種方法是直接在規範中設置@current_user變量。再次,獲取指向您的控制器實例的指針,然後執行x = mock("user"); controller.instance_variable_set(:@current_user, x),然後您可以在x上模擬/存根方法。

相關問題