【问题标题】:Cucumber test double: scenario failing but its steps passingCucumber test double:场景失败但其步骤通过
【发布时间】:2012-06-03 11:34:23
【问题描述】:

我正在使用The RSpec Book 学习 Rspec + Cucumber。我才刚刚开始,正在开发 Codebreaker 游戏。

其中有一个功能“Codebreaker 开始游戏”,它代表用户在 shell 中键入命令并得到两个响应:“欢迎使用 Codebreaker!”和“输入猜测:”。这是该功能的外观:

Feature: code-breaker starts game
   As a code-breaker
   I want to start a game
   So that I can break the code

   Scenario: start game
      Given I am not yet playing
      When I start a new game
      Then I should see "Welcome to Codebreaker!"
      And I should see "Enter a guess:"

由于cucumber 脚本使用了输出,因此本书正在创建一个模拟对象output,它期望接收带有Welcome to Codebreaker!Enter a guess: 参数的puts 消息。这是它在步骤定义中的样子:

#the mock object
class Output
   def messages
      @messages ||= []
   end

   def puts(message)
      messages << message
   end
end

def output
   @output ||= Output.new
end

Given /^I am not yet playing$/ do
end

When /^I start a new game$/ do
   game = Codebreaker::Game.new(output)
   game.start
end

Then /^I should see "([^"]*)"$/ do |message|
   output.messages.should include(message)
end

好的,到现在都没问题。

做这个练习,我记得之前看过rspeck doubles框架可以用在cucumber里面,所以我想我可以稍微清理一下。

首先,我在support/env.rb 中包含了rspeck doubles 框架:

require 'cucumber/rspec/doubles'

然后我更改了步骤定义:

Given /^I am not yet playing$/ do
end

When /^I start a new game$/ do
   @output = double('output').as_null_object #the mock object
   game = Codebreaker::Game.new(@output)
   game.start
end

Then /^I should see "([^"]*)"$/ do |message|
   @output.should_receive(:puts).with(message)
end

奇怪的想法是,现在,当我用黄瓜执行功能时,在总结中我得到了所有 4 个步骤,但不是整个场景。这怎么可能?这是怎么回事?这是我从命令行得到的输出:

Feature: code-breaker starts game
   As a code-breaker
   I want to start a game
   So that I can break the code

  Scenario: start game                          # features/codebreaker_starts_game.feature:6
    Given I am not yet playing                  # features/step_definitions/codebreaker_steps.rb:1
    When I start a new game                     # features/step_definitions/codebreaker_steps.rb:4
    Then I should see "Welcome to Codebreaker!" # features/step_definitions/codebreaker_steps.rb:10
    And I should see "Enter a guess:"           # features/step_definitions/codebreaker_steps.rb:10
      (Double "output").puts("Welcome to Codebreaker!")
          expected: 1 time
          received: 0 times (RSpec::Mocks::MockExpectationError)
      /home/a_user/www/codebreaker/features/step_definitions/codebreaker_steps.rb:11:in `block in <top (required)>'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/error_generator.rb:80:in `__raise'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/error_generator.rb:39:in `raise_expectation_error'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/message_expectation.rb:251:in `generate_error'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/message_expectation.rb:207:in `verify_messages_received'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/method_double.rb:117:in `block in verify'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/method_double.rb:117:in `each'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/method_double.rb:117:in `verify'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/proxy.rb:88:in `block in verify'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/proxy.rb:88:in `each'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/proxy.rb:88:in `verify'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/methods.rb:116:in `rspec_verify'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/space.rb:11:in `block in verify_all'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/space.rb:10:in `each'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks/space.rb:10:in `verify_all'
      /var/lib/gems/1.9.1/gems/rspec-mocks-2.10.1/lib/rspec/mocks.rb:19:in `verify'
      /var/lib/gems/1.9.1/gems/cucumber-1.1.9/lib/cucumber/rspec/doubles.rb:12:in `After'

Failing Scenarios:
cucumber features/codebreaker_starts_game.feature:6 # Scenario: start game

1 scenario (1 failed)
4 steps (4 passed)
0m0.009s

【问题讨论】:

    标签: ruby rspec mocking cucumber bdd


    【解决方案1】:

    当您设置像should_receive 这样的期望时,您指定在将来的某个时间点应该调用指定的方法 - 之前发生的任何事情都将被忽略(否则应该是 have_received 或类似的东西过去时)。

    在您的代码中,您在 Then 步骤中设置了期望,但该方法在您的 When 步骤(即之前)中被调用,因此此时没有设置期望。您的双重设置允许调用任何方法,因此您不会收到任何错误,但是当规范检查最后是否满足所有期望时,它会拒绝并引发异常

    【讨论】:

    • 好的!我明白了,非常感谢@FrederickCheung。也许这就是在黄瓜中不鼓励嘲笑的原因之一,因为必须将事件声明为与期望分开。当然,我应该存根更好,因为它是在书中完成的(因为它正在检查状态而不是行为)。请,如果我的推理有误,请告诉我,我是所有这些东西的新手 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 2021-06-07
    • 1970-01-01
    • 2015-11-21
    • 2014-01-01
    • 1970-01-01
    相关资源
    最近更新 更多