在期望Rspec方法中何时使用花括号与括号?

Hom*_*ith 24 ruby rspec

我做了一个测试:

expect(@parser.parse('adsadasdas')).to raise_error(Errno::ENOENT)
Run Code Online (Sandbox Code Playgroud)

它不起作用.我改为:

expect { @parser.parse('adsadasdas') }.to raise_error(Errno::ENOENT)
Run Code Online (Sandbox Code Playgroud)

它奏效了.

我们什么时候使用花括号?何时使用括号和expect?

Alv*_*Lee 35

为了回应OP的评论,我编辑并完全重写了我的答案.我意识到我的原始答案过于简单,以至于它被认为是不正确的.

您的问题实际上是由其他StackOverflow问题解决的.

一张海报,彼得阿尔文,他说:

至于规则,如果您正在尝试测试行为(例如,引发错误,更改某些值),则会传递块或Proc.否则,您传递一个"常规"参数,在这种情况下,该参数的值是经过测试的.

你遇到这种现象的原因与引发错误有关.当你@parser.parse('adsadasdas')作为参数传递(使用括号)时expect,你实际上是在告诉ruby:

  1. @parser.parse('adsadasdas')首先评估.
  2. 获取结果并将其传递给expect.
  3. expect应该看看这个结果是否与我的期望相符(也就是说,这Errno:ENOENT会被提出).

但是,会发生什么:当ruby评估时@parser.parse('adsadasdas'),会立即出现错误.Ruby甚至没有机会将结果传递给expect.(对于我们关心的所有人,你可以@parser.parse('adsadasdas')作为参数传递给任何函数......比如multiply()capitalize())错误被提出,expect甚至从未有机会完成它的工作.

但是当你@parser.parse('adsadasdas')作为proc(代码块)传递给expect使用花括号时,你告诉ruby的是:

  1. expect,准备做一些工作.
  2. expect,我希望你跟踪我们评估时会发生什么@parser.parse('adsadasdas').
  3. 好吧,expect刚刚评估的代码块是否会引发Errno:ENOENT错误?我当时也在期待它.

当您传递代码块时expect,您告诉expect您希望它检查结果行为,代码块执行所做的更改,然后让您知道它是否符合您提供的期望.

当你传递一个参数时expect,你告诉ruby在参与之前 评估该参数是否达到某个值expect,然后你传递该值expect以查看它是否符合某种期望.


Myr*_*ton 9

TL; DR:用于expect(exp)指定有关的exp并用于expect { exp }指定执行时产生的副作用exp


让我们打开包装。RSpec的大多数匹配器都是匹配器。它们与任何红宝石对象匹配(或不匹配)。相反,少数RSpec的匹配器只能与一个块进行匹配,因为它们必须在块运行时观察该块,以使其正常运行。这些匹配器涉及在块执行期间发生(或不发生)的副作用。除非传递了一个要执行的块,否则匹配器将无法判断命名的副作用是否已经发生。让我们一一考虑内置块匹配器(从RSpec 3.1开始):

raise_error

考虑到可以从方法中返回异常,这与引发异常不同。引发异常是一种副作用,并且只有匹配器通过执行带有适当rescue子句的块才能观察到。因此,该匹配器必须收到一个块才能正常工作。

throw_symbol

引发符号类似于引发错误-引发堆栈跳转,这是一个副作用,只能通过在适当的块内运行一个块才能观察到catch

change

状态突变是一个副作用。匹配器只能通过先检查状态,运行块然后再检查状态来判断某个状态是否发生了变化。

output

I / O是一个副作用。为了使output匹配器正常工作,必须使用新的StringIO 替换适当的流($stdout$stderrStringIO, execute the block, restore the stream to its original value, and then check the contents of the

yield_control/ yield_with_args/ yield_with_no_args/yield_with_successive_args

这些匹配器有些不同。Yielding并不是真正的副作用(实际上只是调用方提供的另一个函数的语法糖),但是无法通过查看表达式的返回值来观察yield。为了使良率匹配器正常工作,它们提供了一个probe对象,您可以使用以下&probe语法将其作为块传递给被测方法:

expect { |probe| [1, 2, 3].each(&probe) }.to yield_with_successive_args(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

这些匹配器有什么共同点?它们都无法处理简单的红宝石值。相反,它们都必须在适当的上下文中包装一个块(即,抢救,捕获或检查值之前/之后)。

请注意,在RSpec 3中,我们添加了一些逻辑,以在用户使用expect给定匹配器使用错误格式时为用户提供明确的错误。但是,在的特定情况下expect(do_something).to raise_error,我们无法为您提供清晰的解释-如果do_something引发错误(如您期望的那样),则在ruby计算to参数之前会引发错误(raise_error匹配器) ),因此RSpec无法与匹配器进行核对,以了解其是否支持价值或阻碍期望。


Gia*_*yen 6

简而言之:

  • 使用大括号(一个块):当你想测试behavior
  • 当你想测试时使用括号returned value

值得一读:As for rules, you pass a block or a Proc if 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.-来自这个答案

  • 能够以简短、简洁的方式总结事情是一种天赋。 (2认同)