ruby - 为什么这个 Ruby 条件赋值没有被内存?

标签 ruby rspec

谁能解释为什么这个规范失败了?

RSpec 结果:

User#presenter memoizes presenter
     Failure/Error: user.presenter
       (<UserPresenter (class)>).new(...)
           expected: 1 time with any arguments
           received: 2 times with arguments: (...)

根据我对条件赋值运算符的理解,它应该只对 @presenter 赋值一次。

 # app/models/user.rb
def User
    def presenter
        @presenter ||= UserPresenter.new(self)
    end
end 

# app/presenters/user_presenter.rb
class UserPresenter
end

# spec/models/user_spec.rb
describe User do

    let(:user){ build_stubbed(:user) }

    describe "#presenter" do
        it "memoizes presenter" do
            UserPresenter.should_receive(:new).once
            user.presenter
            user.presenter # should not call .new
        end
    end
end

最佳答案

问题是这一行:

UserPresenter.should_receive(:new).once

这段代码简单地设置了 UserPresenter 将接收一次 new 方法的预期。它会拆除您原来的 UserPresenter#new 方法,并将其替换为返回 nil 的方法。因为 nil 是假的,所以 @presenter 实例变量没有被内存。

要解决此问题,您可以在期望中指定一个返回值:

UserPresenter.should_receive(:new).once.and_return "some truthy value"

或等效

UserPresenter.should_receive(:new).once { "some truthy value" }

或者如果你绝对想调用原始方法

UserPresenter.should_receive(:new).once.and_call_original

或者使用新的 expect 语法

expect(UserPresenter).to receive(:new).once.and_call_original

参见 this有关期待消息的更多信息,以及 this有关调用原始方法的更多信息。 This对 RSpec 的 should_receive 方法有一些进一步的讨论。

关于ruby - 为什么这个 Ruby 条件赋值没有被内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23710331/

相关文章:

ruby-on-rails - Markdown 外部图像链接与 Redcarpet

ruby - 为什么我会收到 "Sinatra: Up and Running"game.rb "Rock Paper Scissors"的语法错误?

ruby-on-rails - Rails/Rspec - 在 Controller 中测试重定向

ruby - 使用 JRuby 进行 RCov

ruby-on-rails - RSpec:期望改变多个

arrays - Rspec 将空数组解释为缺少 Grape 参数

ruby-on-rails - Ruby 标准库的 Unix 手册页? Rails 怎么样?

ruby - 为什么在 Ruby 的方法中不能有类?

Ruby 正则表达式非捕获组

Ruby "multiply"函数攻略