我正在使用一个小方法来检查租户是否启用了功能。每个租户都有一个存放旗帜的租户计划。我还在Tenant模型上有一些标志,可以用来覆盖特定于计划的标志。在租户模型中,一个小特征检测方法如下所示:
def has_feature?(feature, feature_default = false)
if tenant_plan
feature = "#{feature}_enabled?".to_sym
return tenant_plan.send(feature) || (respond_to?(feature) and send(feature))
end
feature_default
end
我对这个问题最感兴趣的部分是:
(respond_to?(feature) and send(feature))
我正在检查Tenant模型上是否存在同名字段,如果有,则会得到结果。
如果我使用控制台来检查这个:
[1] pry(main)> false and tenant.send(:free_courses_enabled?)
=> false
[2] pry(main)> true and tenant.send(:free_courses_enabled?)
NoMethodError: undefined method `free_courses_enabled?' for #<Tenant:0x007f8f7171d6c8>
from /Users/typeoneerror/.rvm/gems/ruby-2.2.4@doki/gems/activemodel-4.2.7.1/lib/active_model/attribute_methods.rb:433:in `method_missing'
如果Tenant没有send
功能方法,我希望respond_to?
甚至不被调用,这在控制台测试中看起来就像是这样,但我在测试中发现即使respond_to?
返回false,也会调用send,但不会引发NoMethodError
。
expect(tenant).not_to receive(:free_courses_enabled?)
结果:
expected no Exception, got #<RSpec::Mocks::MockExpectationError: (#<Tenant:0x007fdfd908a2a8>).free_courses_enabled?(no args)
expected: 0 times with any arguments
received: 1 time> with backtrace:
有点滑稽,当我期待相反时:
expect(tenant).to receive(:free_courses_enabled?).and_call_original
我们得到了
NoMethodError:
undefined method `free_courses_enabled?' for #<Tenant:0x007f8254bfedd8>
我很茫然。
在这种情况下,ruby是否会在调用方法时吞下NoMethodError
异常,因为表达式的第一部分返回false?非常感谢您的解释,并乐于听取有关重写的任何建议。
它让我看起来像是一个带有ActiveModel的RSpec错误。当我没有添加期望时,当我在开发中运行代码时,它会按预期运行。
答案 0 :(得分:0)
我想在把我的脑子投入各种图书馆后,我想到了这一点。 Tenant
未定义名为payment_options_features?
的方法,因此当我进入控制台并执行此操作时:
tenant.respond_to?(:payment_options_features?) # false
但是,我相信我希望租户不应该在我的RSpec测试中接收这个方法......
expect(tenant).not_to receive(:payment_options_features?)
实际上在租户对象上创建了该函数的模拟,所以当测试运行时:
tenant.respond_to?(:payment_options_features?) # true
因为它被“嘲笑”了。另一种方法是这样做,因为我们知道send
是一种应该始终存在的方法。
expect(tenant).not_to receive(:send).with('payment_options_features?')