【发布时间】:2013-01-16 07:20:42
【问题描述】:
试图遵循 demeter 定律,我正在重构代码。目标是让每个模型都有方法,作为其他模型提取数据的 API。
组织有一个实例方法#suppliers_for_purchaser,它返回一个采购员的所有供应商。此方法已在 organization_spec.rb 中测试成功。
Price 有一个类方法 .latest_prices_for_purchaser。此类方法采用一个参数(Organization 的实例)并使用此参数调用 Organization#suppliers_for_purchaser。这会导致 RSpec 中出现错误架构不存在:
Failures:
1) Price.latest_prices_for_purchaser returns latest prices for purchaser
Failure/Error: Price.latest_prices_for_purchaser(purchaser).should have(2).prices
ActiveRecord::StatementInvalid:
PG::Error: ERROR: schema "organization" does not exist
: SELECT COUNT(*) FROM "organizations" INNER JOIN "partnerships" ON "organizations"."id" = "partnerships"."partner_id" WHERE "partnerships"."organization_id" = 1 AND (organization.organization_role.name = 'supplier')
# ./spec/models/price_spec.rb:24:in `block (3 levels) in <top (required)>'
模型(简化)
class Organization < ActiveRecord::Base
# self referencing n:n table
has_many :partners, :through => :partnerships
# some more associations, all tested
# successfully tested in an RSpec unit test for this model
def suppliers_for_purchaser
partners.where('organization.organization_role.name = ?', "supplier")
end
end
class Price < ActiveRecord::Base
def self.latest_prices_for_purchaser(purchaser)
suppliers = purchaser.suppliers_for_purchaser
# some more code that doesn't get executed because it crashes on the line above
end
end
price_spec.rb(简化版)
describe Price do
describe ".latest_prices_for_purchaser" do
# passes
it "responds" do
Price.should respond_to(:latest_prices_for_purchaser)
end
it "returns latest prices for purchaser" do
purchaser = create(:organization_purchaser)
supplier = create(:organization_supplier)
partnership = create(:partnership, organization: purchaser, partner: supplier)
2.times do
price = create(:price, created_at: 10.hours.ago, supplier: supplier, purchaser: purchaser)
end
Price.latest_prices_for_purchaser(purchaser).should have(2).prices
end
end
end
更新
cheeseweasel 找到了解决方案。单元测试 Price.latest_prices_for_purchaser 仅在将 Organization#suppliers_for_purchaser 更改为:
partners.joins(:organization_role).where('organization_roles.name = ?', "supplier")
【问题讨论】:
-
我不太明白它是如何工作的,但也许我错过了什么?你能告诉我们工作测试吗?另外,你不能摆脱这个位吗:
Organization.find(self).? -
谢谢,我摆脱了
Organization.find(self)。我还在底部包括了工作测试。我是单元测试的新手,一般来说,是否可以测试一个调用另一个模型的实例方法的类方法? -
不用担心,您的组织测试并没有测试供应商_for_purchaser,这正是我认为您的意思。我不确定你的确切结构,但这样的事情能让你走到任何地方:
partners.joins(:organization_roles).where('organization_roles.name = ?', "supplier")? -
谢谢,我认为这是朝着正确方向迈出的一步。现在的错误是
ActiveRecord::ConfigurationError: Association named 'organization_roles' was not found; perhaps you misspelled it?。我包含了 factory.rb 文件,因此您可以看到已设置关联。当一个方法调用另一个模型的方法时,他们会迷路吗? -
抱歉,应该是
joins(:organization_role),尽管它取决于模型中的关联名称。这有帮助吗?
标签: ruby-on-rails ruby-on-rails-3 rspec rspec2 rspec-rails