在 Capybara (Rails) 中使用 Mocha 伪造 ActiveRecord::Associations::CollectionProxy
Faking ActiveRecord::Associations::CollectionProxy with Mocha in Capybara (Rails)
我有一个非常简单的数据结构:一个User
has_manyfilters
和一个Filter
belongs_to一个user
。对于我的测试,我使用 Capybara, minitest-rails and mocha(没有 rspec)。
我正在努力对 Filter
的 ActiveRecord
集合进行充分存根。这是我目前拥有的:
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) }
我有一个非常简单的数据结构:一个User
has_manyfilters
和一个Filter
belongs_to一个user
。对于我的测试,我使用 Capybara, minitest-rails and mocha(没有 rspec)。
我正在努力对 Filter
的 ActiveRecord
集合进行充分存根。这是我目前拥有的:
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) }