2010-10-24 75 views
3

我需要模擬如下:如何模擬已模擬對象的實例方法?

Class User 
    def facebook 
    #returns an instance of a facebook gem 
    end 
end 

所以在我的用戶測試,訪問用戶的Facebook信息,我需要調用user.facebook.me.info檢索其信息。如果我想嘲笑這個,我目前使用下列內容:

@user = Factory(:user) 
facebook = mock() 
me = mock() 
me.expects(:info).returns({"name" => "John Doe"}) 
facebook.expects(:me).returns(me) 
@user.expects(:facebook).returns(facebook) 
assert_equal "John Doe", @user.facebook.me.info["name"] 

這工作,但似乎有點笨拙,有沒有更好的方式來做到這一點?

[編輯]我用摩卡作爲嘲諷的框架

+0

你正在使用哪個模擬框架? – Reactormonk 2010-10-24 14:56:39

+0

我正在使用摩卡。 – pjaspers 2010-10-24 16:06:51

回答

12

你可以嘗試這樣的事情: -

user = Factory(:user) 
user.stubs(:facebook => stub(:me => stub(:info => {:name => "John Doe"}))) 

如果你真的要檢查所有的這些方法被稱爲(我懷疑你沒有),你可以做到以下幾點: -

user = Factory(:user) 
user.expects(:facebook => mock(:me => mock(:info => {:name => "John Doe"}))) 

它更詳細一點,但它通常是值得給予每個模擬對象的名稱: -

user = Factory(:user) 
user.stubs(:facebook => stub('facebook', :me => stub('me', :info => {:name => "John Doe"}))) 

我希望有幫助。

+0

這看起來像那裏最乾淨的解決方案。謝謝! – pjaspers 2010-12-03 09:54:42

0

如果你不想檢查所有的方法被調用,你也可以使用不同的替代方案來嘲笑。例如,你可以使用OpenStruct。

@user = Factory(:user) 
facebook = mock() 
me = mock() 
me.expects(:info).returns({"name" => "John Doe"}) 
facebook.expects(:me).returns(me) 
@user.expects(:facebook).returns(facebook) 
assert_equal "John Doe", @user.facebook.me.info["name"] 

成爲

@user = Factory(:user) 
@facebook = OpenStruct.new(:me => OpenStruct.new(:info => {:name => "John Doe"})) 
@user.expects(:facebook).returns(@facebook) 

該解決方案也爲您提供的好處是可以在測試中改變@facebook屬性,如果你需要測試不同的條件。