在 Capybara (Rails) 中使用 Mocha 伪造 ActiveRecord::Associations::CollectionProxy

Faking ActiveRecord::Associations::CollectionProxy with Mocha in Capybara (Rails)

我有一个非常简单的数据结构:一个Userhas_manyfilters和一个Filterbelongs_to一个user。对于我的测试,我使用 Capybara, minitest-rails and mocha(没有 rspec)。

我正在努力对 FilterActiveRecord 集合进行充分存根。这是我目前拥有的:

require 'test_helper'

class TestExample < Capybara::Rails::TestCase

    let(:user) { FactoryGirl.create(:user) }

    def setup
        # Create some mock filters:
        f1 = Filter.new
        f1.stubs(:id).returns(1)
        f1.stubs(:user_id).returns(1)
        f1.stubs(:title).returns("First Filter")
        f1.stubs(:value).returns(123)

        f2 = Filter.new
        f2.stubs(:id).returns(2)
        f2.stubs(:user_id).returns(1)
        f2.stubs(:title).returns("Second Filter")
        f2.stubs(:value).returns(456)

        fake_filters = [f1, f2]
        user.stubs(:filters).returns(fake_filters)

    end

    def test_user_has_correct_number_of_mocked_filters
        assert_equal(user.filters.count, 2)
    end

    def test_users_mocked_filters_have_correct_ids
        assert_equal(user.filters.pluck(:id), [1, 2]) # ERROR
    end

end

第二个测试抛出错误,因为它们不是 Array.

pluck() 方法

这将如何实现?我希望测试表现得好像 Filter table.

中确实有记录

Pluck 是一种仅限于 ActiveRecord::Relation 的方法,因此除非您还在 fake_filters 上存入一个名为 pluck 的方法,就像您在 Filter

上所做的那样

但是,我会做的只是使用 .map(&:id) 而不是 .pluck(:id)。 map 和 pluck 之间的区别在于 map 在查询期间效率不高,因为在 pluck 的情况下它将执行 SELECT * FROM filters 而不是 SELECT id FROM filters。 Map 还允许查询对象响应的任何内容,而不仅仅是活动记录属性。不过,在这里,应该没问题。

你真的不应该在使用 Capybara 时模拟对象,它是为了完整的 integration/feature 测试。相反,您应该像为用户

一样使用 factory_girl 来构建它们
factory :user do
  # you current user factory code
  # stays here

  factory :user_with_filters do
    transient do
      filters_count 2
    end
    after(:create) do |user, proxy|
      create_list(:filter, proxy.filters_count, user: user)
    end
  end
end

然后代替 let(:user) { FactoryGirl.create(:user) }let(:user) { FactoryGirl.create(:user_with_filters) }