Rspec:我如何测试阵列推送?

时间:2013-09-01 05:26:51

标签: ruby-on-rails rspec

我正在Rspec中编写一些测试,并尝试通过carrier关联将user推送到has_and_belongs_to_many。下面是我写的测试,但是我用箭头表示的线似乎没有通过。我意识到我嘲笑了运营商而不是用户,我想知道这是否会导致HABTM协会出现问题。这是问题还是还有其他我想念的东西?我是嘲笑和捣蛋的新手,但我会尽我所能!

describe UsersController do
  describe 'get #add_carrier' do
    let(:user) { build(:approved_user) }

    let(:carrier) { mock_model(Carrier).as_null_object }
    before{ Carrier.stub(:find).and_return(carrier) }

    it 'associates the Carrier to the User' do
      expect(user.carriers).to eq []
      user.should_receive(:carriers).and_return([])
  --> (user.carriers).should_receive(:push).with(carrier).and_return([carrier])
      (user.carriers).push(carrier)
      (user.carriers).should include carrier
    end 
  end
end

1 个答案:

答案 0 :(得分:0)

当您想要进行适当的单元测试并且除了被测方法之外的任何东西时,通常会使用存根。当您测试调用命令方法的方法(即具有某些影响的方法,例如更改某些数据或保存记录)并且您希望确保调用它时,通常会使用模拟(具有预期的存根)。

这个特殊的测试,在控制器中给出,似乎是在错误的级别测试 - 它测试方法内部的东西,而不是方法本身。看看rspec docs

不知道您正在测试的代码,确切地确定如何测试有点棘手。 #add_carrier听起来像一个方法,应该只测试是否添加了载波,所以我们可能会测试消息的期望。这个测试似乎也在测试getter方法#carriers,这对于一个单元测试来说似乎有点多了(但我完全理解将它放在那里的愿望)。

另请注意,分享您获得的错误肯定会有所帮助。

无论如何,请尝试以下内容:

describe UsersController do
  describe 'get #add_carrier' do # Should this really be a GET?
    subject { get :add_carrier }

    let(:user) { build(:approved_user) }
    let(:carrier) { mock_model(Carrier).as_null_object }

    before do
      controller.stub(:user) { user }
      Carrier.stub(:find) { carrier }
    end

    it "associates the Carrier to the User" do
      user.carriers.should_receive(:push).with(carrier).and_call_original
      subject
      user.carriers.should include carrier
    end
  end
end

对user.carriers的原始值没有期望(应该在User模型中测试)。对推送如何工作的细节没有期望 - 再次,应该在别处测试。相反,只需确认调用重要的命令消息。我不是100%肯定我们甚至应该做#and_call_original并确认结果,因为这些是我们也可以在模型单元测试中测试的东西(Carrier#push的结果),但为了安心我在这里。

请注意,这一切都是从内存中写的,所以如果有任何内容无效,请告诉我。