我正在开发Ruby on Rails应用程序,我有一个BillingPlan
模型,其中包含以下方法:
class BillingPlan < ActiveRecord::Base
# ...
def billing_months
dates = [Date.new(Date.today.year, start_month.value, billing_day)]
while dates.size < billings_in_year
dates << dates.last + recurrence.value.months
end
dates.map{ |d| d.month }
end
def billings_in_year
12 / recurrence.value
end
end
为了测试代码,我编写了以下规范:
describe BillingPlan do
# ...
describe '#billings_in_year' do
subject do
(plan = BillingPlan.new).stubs(
recurrence: stub(value: 4)
) && plan
end
it 'returns the number of billings in a year' do
expect(subject.billings_in_year).to eq(3)
end
end
describe '#billing_months' do
subject do
(plan = BillingPlan.new).stubs(
recurrence: stub(value: 2),
start_month: stub(value: 2),
billings_in_year: 6,
billing_day: 21
) && plan
end
it 'returns the months when billing is done' do
expect(subject.billing_months).to eq([2, 4, 6, 8, 10, 12])
end
end
end
正如您所看到的,我已经设法通过使用Mocha完全隔离这两种方法。但是,我想知道我在测试中是否滥用存根?是不是太依赖于方法的内部运作?你能否提供一般规则来了解一个人应该依赖嘲弄/伪装的广泛程度?
注意:recurrence
和start_month
是第三方类的对象。
答案 0 :(得分:2)
你的测试存根他们需要隔离他们测试的案例,但他们确实暗示你的方法有问题 - 他们不遵守Law of Demeter:
- 你可以自己玩。
- 您可以玩自己的玩具(但不能将它们分开),
- 你可以玩给你的玩具。
- 你可以玩自己制作的玩具。
存根存根值所需的每个地方 - 你都有问题。
假设这是一个Rails程序,更改它非常容易 代码满足法律。首先,我们对它进行了单行添加 用户类:
class User delegate :name, :to => :department, :prefix => true, :allow_nil => true # ... end
如果此解决方案由于某种原因不可行,您可以使用此解决方案:
Demeter不会阻止我们与物体互动 - 和三阶联想;它只是声称我们无法互动 与所有这些对象在同一方法中。再看看 法律的制定:
... M向其发送消息的所有对象......
Demeter只是关于方法的规则;它不限制集合 类可以与类进行交互。
所以这是完全合法的:
class StatPresenter def human_stats(human) "Age: #{human.age}.nCountry stats:n#{country_stats(human.country)}" end def country_stats(country) " Mortality rate: #{country.mortality_rate}" end end