Rspec如何确定是否已定义let块?

huangapple go评论65阅读模式
英文:

Rspec how to determine if a let block has been defined?

问题

在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?的方法或类似的方法?

英文:

In Rspec, I want to take advantage of using super() to call a defined let block if it exists or set a new value if it hasn't, I want to use this within a shared_example group but I just can't find how to do this.

I've tried checking if @some_let exists, I've tried checking if a super method of :some_let is owned by the kernel or not and none of them provide anything useful; I can't access instance_methods or instance_method because Rspec won't let me and searching the internet for a method hasn't revealed an answer.

I want to be able to do something like this:

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

is there a method like let_exists? or something to that effect?

答案1

得分: 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

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

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

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

describe 'with let' do
  include_examples 'a shared example'   # <- 顺序很重要
  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
英文:

Assuming that you call let before including the shared examples, this would work:

shared_examples &#39;a shared example&#39; do
  let(:some) { &#39;fallback value&#39; } unless method_defined?(:some)
end

describe &#39;with let&#39; do
  let(:some) { &#39;explicit value&#39; }
  include_examples &#39;a shared example&#39;

  it { expect(some).to eq(&#39;explicit value&#39;) }
end

describe &#39;without let&#39; do
  include_examples &#39;a shared example&#39;

  it { expect(some).to eq(&#39;fallback value&#39;) }
end

method_defined? checks if a method called some has already been defined in the current context. If not, the method is defined to provide a default value.

Another (usually easier) approach is to always define a default value and to provide the explicit value after including the shared examples: (thus overwriting the default value)

shared_examples &#39;a shared example&#39; do
  let(:some) { &#39;default value&#39; }
end

describe &#39;with let&#39; do
  include_examples &#39;a shared example&#39;   # &lt;- order is
  let(:some) { &#39;explicit value&#39; }       #    important

  it { expect(some).to eq(&#39;explicit value&#39;) }
end

describe &#39;without let&#39; do
  include_examples &#39;a shared example&#39;

  it { expect(some).to eq(&#39;default value&#39;) }
end

huangapple
  • 本文由 发表于 2020年1月6日 20:31:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/59612181.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定