[英]How to test chained methods in Ruby on Rails using Rspec
我正在尝试决定如何测试一种简单地计算相关记录上的平均值的方法。 我担心测试实现与返回的实际结果。
假设我有以下型号...
class User
has_many :interviews
def interview_grade
interviews.average(:score).round unless interviews.empty?
end
end
class Interview
belongs_to :user
end
在user_spec.rb
我有...
describe "interview_grade" do
let(:user) {User.new}
context "when the user has interviews" do
before { user.stub_chain(:interviews, :empty?){false} }
it "should return an average of the appraisal ratings" do
user.interviews.should_receive(:average).with(:score).and_return(3.2)
user.work_history_grade.should == 3
end
end
context "when the user has no interviews" do
before {Interview.destroy_all}
it "should return nil" do
user.interview_grade.should be_nil
end
end
end
这些测试通过了,但我觉得它很脆弱。 如果interview_grade
应该实际计算分数的总和(例如)怎么办。 因为我只是在测试是否调用了特定的方法链,所以这个通过测试不会告诉我结果实际上是不正确的。
我已经尝试对user.interviews
进行存根,以便为测试设置可用的分数,但这在 Rails 3 中似乎很棘手,因为关联是延迟加载的。 即我不能只创建一个采访对象数组,因为它不响应平均method
。
非常感谢任何建议。
3年后回到这个话题。 我会以完全不同的方式处理它。
下面代码的好处是,为了为 InterviewGrader 编写测试,我不再需要担心如何获得分数。
我只是给它打分并测试它给了我正确的 output。
此外,我永远不需要担心 InterviewGrader 的底层实现。 但是,如果以后更改逻辑,则测试将失败。
User
上的新scores
方法需要单独测试。
class InterviewGrader
def self.run scores
new(scores).run
end
attr_reader :scores
def initialize(scores)
@scores = scores
end
def run
scores.inject { |sum, score|
sum + score
}.to_f / number_of_scores
end
private
def number_of_scores
scores.length
end
end
class User
has_many :interviews
def scores
interviews.map(&:score)
end
def interview_grade
InterviewGrader.run(scores)
end
end
class Interview
belongs_to :user
end
这是存根和 mocking 的错误使用。
在这种情况下,您应该只测试interview_grade
是否有效,当average
返回 nil 时(这只是使用了interviews.empty?
的案例)。
average
方法是由rails本身测试的。 ruby 测试的round
方法(我猜)。 所以你不需要测试这个方法。 这是仅测试您自己的代码的一般想法。
如果你想测试,interview_grade 是如何计算的,你应该创建测试数据(带有夹具或工厂)。 因为您应该测试系统的单独(在某些情况下)部分,而在这种情况下,分离是错误的: interviews.average 和 interviews.empty? 依赖于您的代码,但在规范中它们是独立的。
def interview_grade
interviews.average(:score).try(:round)
end
如果您以这种方式重写您的方法,则无需存根和 mocking
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.