RSpec测试问题:类方法与实例方法区分及报错修复
解决RSpec测试类方法与实例方法区别的问题
我来帮你搞定这个测试问题,同时完美展示类方法和实例方法的核心区别。
首先看你遇到的报错:NoMethodError: undefined method 'convert_to_pdf' for #<Invoice:0x007fa48e2b2ac0>,这其实是完全符合预期的——因为你定义的convert_to_pdf是类方法(用self.前缀声明),只能通过类本身调用,实例对象根本没有这个方法。但你的测试失败,核心原因是RSpec断言抛出错误的写法不对!
问题出在这里
你写的:
expect(described_class.new.convert_to_pdf).to raise_error
这种写法会先执行described_class.new.convert_to_pdf,这时候直接抛出NoMethodError,RSpec根本没机会捕获这个错误来做断言,自然就失败了。
正确的做法是把要执行的代码放在一个块里传给expect,这样RSpec会包裹这个代码块,主动捕获里面抛出的错误:
expect { described_class.new.convert_to_pdf }.to raise_error
修正后的完整代码
把第二个测试的断言改成块形式,两个测试就能全部通过,正好能向同事清晰展示类方法和实例方法的区别:
class Invoice def self.convert_to_pdf "Yay" end end RSpec.describe Invoice do describe '#convert_to_pdf' do it "works when called as a class method" do expect(described_class.convert_to_pdf).to eql("Yay") end it "raises an error when called on an instance" do expect { described_class.new.convert_to_pdf }.to raise_error(NoMethodError) end end end
额外补充说明
- 类方法(
self.method_name):属于类本身,只能通过Invoice.convert_to_pdf或者described_class.convert_to_pdf调用,实例对象无权访问。 - 实例方法:如果定义成
def convert_to_pdf(去掉self.),那只能通过Invoice.new.convert_to_pdf调用,类本身不能直接调用。 - 建议在断言抛出错误时,指定具体的错误类型(比如
NoMethodError),这样测试更精准,避免捕获到其他意外的错误。
内容的提问来源于stack exchange,提问作者Faraz Noor
相关产品推荐
相关产品推荐

