Rspec如何判断let块是否已经定义?

The*_*tix 4 ruby rspec rspec-rails

在 Rspec 中,我想利用 usingsuper()来调用已定义的let块(如果存在)或设置新值(如果不存在),我想在组中使用它,shared_example但我只是找不到如何执行此操作。

我尝试过检查是否@some_let存在,我尝试过检查是否:some_let拥有 的超级方法kernel,但它们都没有提供任何有用的东西;我无法访问instance_methods,或者instance_method因为 Rspec 不允许我访问,并且在互联网上搜索方法尚未找到答案。

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

shared_examples 'a shared example' do
  let(:some_let) { let_exists?(:some_let) ? super() : some_new_value }
end
Run Code Online (Sandbox Code Playgroud)

有类似的方法let_exists?或类似的效果吗?

Ste*_*fan 7

假设您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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • @Thermatix RSpec 创建 Ruby 类的层次结构。每个“describe”都会创建一个新类 - 上面的代码创建两个类:“RSpec::ExampleGroups::WithLet”和“RSpec::ExampleGroups::WithoutLet”。调用“let”会在该类中创建一个实例方法。运行示例时,RSpec 创建相应类的实例,这使得这些实例方法可供示例使用。“describe”块以及“shared_examples”块对应于类主体。在类体内,您可以调用“method_define?”来检查是否定义了方法。 (2认同)