【问题标题】:Rspec how to determine if a let block has been defined?Rspec如何确定是否已经定义了一个let块?
【发布时间】:2020-01-06 12:31:17
【问题描述】:

在 Rspec 中,我想利用 super() 调用已定义的 let 块(如果存在)或设置新值(如果不存在),我想在 shared_example 组中使用它,但是我只是找不到如何做到这一点。

我试过检查@some_let 是否存在,我试过检查:some_let 的超级方法是否由kernel 拥有,它们都没有提供任何有用的东西;我无法访问 instance_methodsinstance_method,因为 Rspec 不让我访问,并且在互联网上搜索方法也没有找到答案。

我希望能够做这样的事情:

shared_examples 'a shared example' do
  let(:some_let) { let_exists?(:some_let) ? super() : some_new_value }
end

有没有像let_exists? 这样的方法?

【问题讨论】:

  • if defined?(super),也许吧?
  • super 总是被定义,问题是 RSpec 传播 let 块,因此每个嵌套上下文都有自己的 let 块版本,所以一旦它被定义它总是存在的。更糟糕的是,它甚至不能做像let(:let) { custom_defined_let || default_value } 这样的事情,因为它只会错误custom_defined_let 不存在
  • let(:some_let) { some_new_value } unless method_defined?(:some_let) 会起作用,即仅在方法不存在时才定义它。
  • 这不起作用,因为some_let 只存在于执行上下文中,而不存在于复杂上下文中,就像instance_method 它被阻止了:(
  • 不确定你的意思......你能提供一个更完整的例子来说明你想要实现的目标吗?

标签: ruby rspec rspec-rails


【解决方案1】:

假设您在包含共享示例之前调用let,这将起作用:

shared_examples 'a shared example' do
  let(:some) { 'fallback value' } unless method_defined?(:some)
end

describe 'with let' do
  let(:some) { 'explicit value' }
  include_examples 'a shared example'

  it { expect(some).to eq('explicit value') }
end

describe 'without let' do
  include_examples 'a shared example'

  it { expect(some).to eq('fallback value') }
end

method_defined? 检查当前上下文中是否已经定义了一个名为some 的方法。如果不是,则定义该方法以提供默认值。

另一种(通常更简单)的方法是始终定义默认值并在之后提供显式值,包括共享示例:(从而覆盖默认值)

shared_examples 'a shared example' do
  let(:some) { 'default value' }
end

describe 'with let' do
  include_examples 'a shared example'   # <- order is
  let(:some) { 'explicit value' }       #    important

  it { expect(some).to eq('explicit value') }
end

describe 'without let' do
  include_examples 'a shared example'

  it { expect(some).to eq('default value') }
end

【讨论】:

  • 我很惊讶这个工作,但它确实,我不在乎,我只能推测执行和编译之间共享一些上下文,我认为这更像是说厨师在哪里有一个编译阶段和一个执行阶段,它们存在于不同的上下文中,因此它们之间不共享诸如方法之类的东西。
  • @Thermatix RSpec 创建 Ruby 类的层次结构。每个describe 创建一个新类——上面的代码创建了两个类:RSpec::ExampleGroups::WithLetRSpec::ExampleGroups::WithoutLet。调用let 在该类中创建一个实例方法。运行示例时,RSpec 创建相应类的实例,使这些实例方法可用于示例。 describe 块以及 shared_examples 块对应于类主体。在类体内,您可以调用method_defined? 来检查是否定义了方法。
猜你喜欢
  • 2022-07-28
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多