我正在学习rails(我主要是一名java开发人员),我的问题很明显,而且我在使用我的rspec测试访问模型上的方法时遇到了麻烦。我基本上遵循this tutorial,但将其应用于我自己的项目。我正在尝试将gradu_year定义为基于学生成绩和一年中当前时间的方法。当我实例化对象并在rails控制台中调用方法时,它可以像我期望的那样工作,但是当我在测试中尝试这样做时,我得到了:
undefined method `graduation_year'
class Student < ActiveRecord::Base
validates :school_id, presence: true, uniqueness: true
validates :first_name, presence: true, length: { maximum: 30 }
validates :last_name, presence: true, length: { maximum: 40 }
validates :gender, presence: true, inclusion: { :in => %w(m f M F) }
validates :grade, presence: true, numericality: { greater_than_or_equal_to: 1 , less_than_or_equal_to: 12 }
def graduation_year
year = Date.today.year + ( 12 - grade )
end
end
require 'spec_helper'
describe Student do
before { @student = Student.new(
school_id: 3,
first_name: "Michael",
last_name: "Green",
gender: "M",
grade: 6)}
subject { @student }
it { should respond_to(:school_id) }
it { should respond_to(:first_name) }
it { should respond_to(:last_name) }
it { should respond_to(:gender) }
it { should respond_to(:grade) }
it { should respond_to(:graduation_year) }
it { should be_valid }
describe "when school_id is not present" do
before { @student.school_id = " " }
it { should_not be_valid }
end
.
.
.
describe "when grade is 7 graduation_year should be calculated correctly" do
before { @student.grade = 7 }
expect(@student.graduation_year).to eq(Date.today.year+5)
end
end
~/dev/rails_apps/spec/models/student_spec.rb:96:in `block (2 levels) in <top (required)>': undefined method `graduation_year' for nil:NilClass (NoMethodError)
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `module_eval'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `subclass'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:228:in `describe'
from ~/dev/rails_apps/spec/models/student_spec.rb:94:in `block in <top (required)>'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `module_eval'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `subclass'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:228:in `describe'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/dsl.rb:18:in `describe'
from ~/dev/rails_apps/spec/models/student_spec.rb:3:in `<top (required)>'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `load'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `block in load_spec_files'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `each'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `load_spec_files'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:22:in `run'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:80:in `run'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:17:in `block in autorun'
另外,我不认为这是问题,但我最初将graduation_year
作为Student表上的属性,但删除了它,并且此测试应该验证它是否正确计算。 / p>
我在测试中也尝试了puts first_name
,但是在first_name
上我得到了相同的未定义方法错误。我想我只是错过了ruby / rails工作方式。
答案 0 :(得分:2)
您的期望声明未包含在'it'子句中。试着写
describe "when grade is 7" do
before { @student.grade = 7 }
it 'calculates the graduation year correctly' do
expect(@student.graduation_year).to eq(Date.today.year+5)
end
end
作为旁注,以这种方式使用@student并不是惯用的。你最好使用一个定义学生的let语句。因此,与Student.new相比,您可以编写类似这样的内容:
let(:student) { Student.new(
school_id: 3,
first_name: "Michael",
last_name: "Green",
gender: "M",
grade: 6)}
所有随后对'@student'的引用都将替换为'student'。这可以确保描述块中没有任何泄漏。
let语句将记忆该对象,并且只有在规范中引用student时才会实例化该对象。
答案 1 :(得分:1)
您无法直接在describe
区块内设置期望值,就像您的行一样:
expect(@student.graduation_year).to eq(Date.today.year+5)
你没有说明你得到了什么具体的错误(即什么对象有未定义的方法),但此时@student
将是nil
,因为所有未定义的实例变量都是{{ 1}},因此它不会有nil
方法。但是,如果graduation_year
是一个有效的表达式,那么@student.graduation_year
调用就会得到一个未定义的方法。