ruby Rspec:期望与带块的期望 - 有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19960831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 06:17:53  来源:igfitidea点击:

Rspec: expect vs expect with block - what's the difference?

rubytddrspec2

提问by Amit Erandole

Just learning rspec syntax and I noticed that this code works:

刚刚学习 rspec 语法,我注意到这段代码有效:

  context "given a bad list of players" do
    let(:bad_players) { {} }

    it "fails to create given a bad player list" do
       expect{ Team.new("Random", bad_players) }.to raise_error
     end 
  end

But this code doesn't:

但这段代码没有:

  context "given a bad list of players" do
    let(:bad_players) { {} }

    it "fails to create given a bad player list" do
       expect( Team.new("Random", bad_players) ).to raise_error
     end 
  end

It gives me this error:

它给了我这个错误:

Team given a bad list of players fails to create given a bad player list
     Failure/Error: expect( Team.new("Random", bad_players) ).to raise_error
     Exception:
       Exception
     # ./lib/team.rb:6:in `initialize'
     # ./spec/team_spec.rb:23:in `new'
     # ./spec/team_spec.rb:23:in `block (3 levels) in <top (required)>'

My question is:

我的问题是:

  1. Why does this happen?
  2. What is the difference between the former and later example exactly in ruby?
  1. 为什么会发生这种情况?
  2. 在 ruby​​ 中,前一个和后一个示例之间有什么区别?

I am also looking for ruleson when to use one over the other

我也在寻找规则何时使用一个比其他

One more example of the same but inverse results, where this code works:

另一个相同但相反结果的示例,此代码有效:

  it "has a list of players" do
    expect(Team.new("Random").players).to be_kind_of Array
  end 

But this code fails

但是这段代码失败了

  it "has a list of players" do
    expect{ Team.new("Random").players }.to be_kind_of Array
  end

Error I get in this case is:

我在这种情况下得到的错误是:

Failure/Error: expect{ Team.new("Random").players }.to be_kind_of Array
       expected #<Proc:0x007fbbbab29580@/Users/amiterandole/Documents/current/ruby_sandbox/tdd-ruby/spec/team_spec.rb:9> to be a kind of Array
     # ./spec/team_spec.rb:9:in `block (2 levels) in <top (required)>'

The class I am testing looks like this:

我正在测试的课程如下所示:

class Team
  attr_reader :name, :players

  def initialize(name, players = [])
    raise Exception unless players.is_a? Array

    @name = name
    @players = players
  end
end

回答by nzifnab

As has been mentioned:

正如已经提到的:

expect(4).to eq(4)

This is specifically testing the value that you've sent in as the parameter to the method. When you're trying to test for raised errors when you do the same thing:

这是专门测试您作为参数发送给方法的值。当您尝试在执行相同操作时测试引发的错误时:

expect(raise "fail!").to raise_error

Your argument is evaluated immediatelyand that exception will be thrown and your test will blow up right there.

你的论点会立即被评估,异常将被抛出,你的测试将在那里爆炸。

However, when you use a block (and this is basic ruby), the block contents isn't executed immediately - it's execution is determined by the method you're calling (in this case, the expectmethod handles when to execute your block):

但是,当您使用块(这是基本的 ruby​​)时,块内容不会立即执行 - 它的执行由您正在调用的方法决定(在这种情况下,该expect方法处理何时执行您的块):

expect{raise "fail!"}.to raise_error

We can look at an example method that might handle this behavior:

我们可以看一个可能处理这种行为的示例方法:

def expect(val=nil)
  if block_given?
    begin
      yield
    rescue
      puts "Your block raised an error!"
    end
  else
    puts "The value under test is #{val}"
  end
end

You can see here that it's the expectmethod that is manually rescuing your error so that it can test whether or not errors are raised, etc. yieldis a ruby method's way of executing whatever block was passed to the method.

您可以在这里看到,它expect是手动挽救您的错误的方法,以便它可以测试是否引发了错误等。这 yield是执行传递给该方法的任何块的 ruby​​ 方法的方式。

回答by Peter Alfvin

In the first case, when you pass a block to expect, the execution of the block doesn't occur until it's time to evaluate the result, at which point the RSpec code can catch any error that are raised and check it against the expectation.

在第一种情况下,当您将块传递给 时,块expect的执行不会发生,直到需要评估结果,此时 RSpec 代码可以捕获任何引发的错误并根据预期检查它。

In the second case, the error is raised when the argument to expectis evaluated, so the expectcode has no chance to get involved.

在第二种情况下,当计算参数 to 时会引发错误expect,因此expect代码没有机会参与其中。

As for rules, you pass a block or a Procif you're trying to test behavior(e.g. raising errors, changing some value). Otherwise, you pass a "conventional" argument, in which case the value of that argument is what is tested.

至于规则,Proc如果您尝试测试行为(例如引发错误、更改某些值),则传递块或 a 。否则,您传递一个“常规”参数,在这种情况下,该参数的值就是被测试的值。