如何在rspec中创建嵌套的let?

时间:2016-01-28 23:24:00

标签: rspec

是否可以修改现有的let变量,例如向哈希添加条目:

describe 'my spec' do
  let(:var) { { a: 1, b: 2 } }
  let(:foo) { bar(var) }

  context 'when c is defined' do
    let(:var) { var.merge c: 3 }  # This does not work because it will be evaluated recursively
    # ... actual tests using foo ... 
  end

end

我希望var{ a: 1, b: 2, c: 3 }

3 个答案:

答案 0 :(得分:0)

是的,你创建了一个循环依赖,它不会工作。

我认为最好的解决方案是在需要更改的上下文中将var内容设置为静态:

...
let(:var) { { a: 1, b: 2, c: 3 } }
...

如果您确实需要将哈希与其他内容合并,则以下解决方法可以解决问题,使用before回调更改现有哈希:

describe 'my spec' do
  let(:var) { { a: 1, b: 2 } }
  let(:foo) { bar(var) }

  context 'when c is defined' do
    before { var.merge! c: 3 }
  end
end

答案 1 :(得分:0)

只需在每个var中以所需格式重新定义contextfoo会被懒惰地评估,因此它将使用在var中定义的相应版本每个context最终在it块中调用时:

describe 'my spec' do
  let(:foo) { bar(var) }

  context 'when c is defined' do
    let(:var) { { a: 1, b: 2, c: 3 } }

    it 'returns some result with c' do
      expect(foo).to eq('bar with c') # or whatever it returns
    end 
  end

  context 'when d is defined' do
    let(:var) { { a: 1, b: 2, d: 4 } }

    it 'returns some result with d' do
      expect(foo).to eq('bar with d') # or whatever it returns
    end  
  end
end

修改:如果确实想要嵌套let,那么我会说要么选择Igor's answer,要么基本定义var中的let将不会在规范中进行测试,然后将其放在单独的describe 'my spec' do let(:base_var) { { a: 1, b: 2 } } let(:foo) { bar(var) } context 'when c is defined in var' do let(:var) { base_var.merge(c: 3) } it 'returns some result with c' do expect(foo).to eq('bar with c') # or whatever it returns end end context 'when d is defined in var' do let(:var) { base_var.merge(d: 4) } it 'returns some result with d' do expect(foo).to eq('bar with d') # or whatever it returns end end context 'when no changes made from base_var to var' do let(:var) { base_var } it 'returns some result from just bar' do expect(foo).to eq('just bar') # or whatever it returns end end end 语句中(如果经过测试,那么根据最终示例,您将无法避免重复):

Dim Tbl As ListObject
Dim StrFormula1, StrFormula2 As String
Dim NewRow As ListRow
StrFormula1 = "=HYPERLINK(""#'" & newName & "'!A1"",newName & ""!A1)"
StrFormula2 = "=" & newName & "!C9"

Set Tbl = Range("tblProjects").ListObject
Set NewRow = Tbl.ListRows.Add(AlwaysInsert:=True)
NewRow.Range = Array(StrFormula1, StrFormula2)

答案 2 :(得分:-1)

如果您具有嵌套的RSpec上下文来测试不同参数的行为,则可以通过将更改后的参数合并到super()块中的let(:foo)中来部分覆盖父参数:

describe 'My::Class' do
  let(:foo) do
    {
      'some_common_param' => 'value'
      'role'              => 'default',
    }
  end

  context 'with role => web' do
    let(:foo) do
      super().merge({ 'role' => 'web' })
    end

    it { should compile }
  end
end