2016-04-16 24 views
0

該方法本身按預期工作,但是當我嘗試在模型規範中測試它時,創建部件失敗。查找部分運作良好。我錯過了什麼?rspec模型測試;方法不起作用

conversation.rb

scope :between, -> (sender_id, recipient_id) do 
    where("(conversations.sender_id = ? AND conversations.recipient_id = ?) OR (conversations.sender_id = ? AND conversations.recipient_id = ?)", sender_id, recipient_id, recipient_id, sender_id) 
end 

def self.create_or_find_conversation(task_assigner_id, task_executor_id) 
    Conversation.between(task_assigner_id, task_executor_id).first_or_create do |conversation| 
    conversation.sender_id = task_assigner_id 
    conversation.recipient_id = task_executor_id 
    end 
end 

conversation_spec.rb

describe "class methods" do 

    let(:sender) { create(:user) } 
    let(:recipient) { create(:user) } 
    let(:other_recipient) { create(:user) } 
    let!(:conversation) { create(:conversation, sender: sender, recipient: recipient) } 

    context "create_of_find_conversation" do 

    #this one throws Failure/Error: expect{conv}.to change{Conversation.count}.by(1) 
    #expected result to have changed by 1, but was changed by 0 
    it "creates conversation" do 
     conv = Conversation.create_or_find_conversation(sender, other_recipient) 
     expect{conv}.to change{Conversation.count}.by(1) 
    end 

    #this one is working as expected 
    it "finds conversation" do 
     conv = Conversation.create_or_find_conversation(sender, recipient) 
     expect(conv).to eq(conversation) 
    end 
    end 
end 

回答

3

我認爲這些代碼:

it "creates conversation" do 
    conv = Conversation.create_or_find_conversation(sender, other_recipient) 
    expect{conv}.to change{Conversation.count}.by(1) 
end 

應改爲:

it "creates conversation" do 
    expect{ 
     Conversation.create_or_find_conversation(sender.id, other_recipient.id) 
    }.to change{Conversation.count}.by(1) 
end 

因爲它的價值不是改變了計數,而是改變了過程。

+0

我也嘗試過這種方式,但並沒有幫助。任何其他想法? –

+0

啊,我是個白癡。方法params必須是user_id而不是用戶。 –

+0

你也是對的,它不能與'conv'變量一起工作。 –

0

Ruby中的正則變量不是延遲加載 - 分配的右側在分配變量時進行處理。

def do_something(val) 
    puts "do_something called" 
    val 
end 

a = do_something(hello_world) 
puts a 
# do_something called 
# hello world 

你要麼需要改變厚望,這樣的動作被稱爲傳遞給期望塊中:

it "creates conversation" do 
    expect do 
    Conversation.create_or_find_conversation(sender, other_recipient) 
    end.to change{Conversation.count}.by(1) 
end 

或者需要Rspec的let創建一個延遲加載變量:

let(:conv) { Conversation.create_or_find_conversation(sender, other_recipient) } 

it "creates conversation" do 
    expect { conv }.to change{Conversation.count}.by(1) 
end 

但是,這並不能解決您對域錯誤建模的根本問題。在對話中雙方輪流發言 - 所以使用recipient_idsender_id顯然是錯誤的。而是其具有發送者和接收者的消息

您可以將它們更改爲任何您想要的名稱,但使用適當的多對多關係要簡單得多,因此您不需要複雜的AND OR查詢。

class User < ActiveRecord::Base 
    has_many :user_conversations 
    has_many :conversations, through: user_conversations 
end 

class Conversation < ActiveRecord::Base 
    has_many :user_conversations 
    has_many :users, through: user_conversations 
end 

# the m2m join model. 
class UserCoversation < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :conversation 
end 

然後,您可以簡單地詢問:

Conversation.where(users: [a, b])