当两件事情相等时,RSpec eq matcher会返回失败

时间:2014-10-21 08:50:50

标签: ruby-on-rails rspec

在我的控制器测试中,我正在测试将正确的值分配给实例变量。

当我这样做时

expect(assigns(:conversations)).to eq @user_inbox

RSpec告诉我:

 Failure/Error: expect(assigns(:conversations)).to eq @user_inbox

   expected: #<ActiveRecord::Relation [#<Mailboxer::Conversation id: 4, subject: "Dude, what up?", created_at: "2014-10-21 08:43:50", updated_at: "2014-10-21 08:43:50">]>
        got: #<ActiveRecord::Relation [#<Mailboxer::Conversation id: 4, subject: "Dude, what up?", created_at: "2014-10-21 08:43:50", updated_at: "2014-10-21 08:43:50">]>

   (compared using ==)

   Diff:

我看到预期和实际之间没有区别。我想知道导致此测试失败的原因。

3 个答案:

答案 0 :(得分:4)

ActiveRecord::Relation根据实际关系进行比较,而不是结果集。例如,

User.where(:id => 123) == User.where(:email => "fred@example.com")

将返回false,即使查询结果都相同,因为实际查询不同。

我怀疑您更关心查询结果而不是它的组成方式,在这种情况下,您可以使用to_a将关系转换为活动记录对象数组。请注意,Active Record仅根据id属性的值定义相等性(对于未保存的对象具有特殊情况)。

答案 1 :(得分:0)

是的,因为这是两个ActiveRecord::Relation对象。您的实例变量是第一个,您创建另一个名为conversations

的变量

您应该使用以下内容测试行数或其他属性:

expect(assigns(:conversations).count).to eq @user_inbox.count

答案 2 :(得分:0)

也许你应该改变测试策略。

当您的测试难以编写时,您的代码错误或您的测试策略错误。我建议您在控制器测试中没有测试查询结果。

你应该模拟你的查询结果

describe 'GET user conversations' do
  before do
    your_user.stub(:conversations).and_return "foo bar"       
  end
  it 'assigns the conversations of the user' do
    get :user_conversation
    expect(assigns(:conversations)).to eq your_user.conversations
  end
end

或者您应该测试some_collaborator.should_receive(:some_methods)

describe 'GET user conversations' do
  before do
    some_collaborator.stub(:conversations)
  end
  it 'assigns the conversations of the user' do
    some_collaborator.should_receive(:conversations)
    get :user_conversation
  end
end