Cucumber test double: scenario failing but its steps passing

拈花ヽ惹草 提交于 2019-12-08 12:38:59

问题


I'm learning Rspec + Cucumber with The RSpec Book. I'm just at the beginning, while developing a Codebreaker game.

In it, there is a feature "Codebreaker starts game" that represents simply a user typing a command in the shell and getting two responses: "Welcome to Codebreaker!" and "Enter a guess:". Here it is how the feature looks like:

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:"

As the output is used by the cucumber script, the book is creating a mock object output which is expecting to receive the puts message with Welcome to Codebreaker! and Enter a guess: argument. Here it is how it looks in the step definitions:

#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

Ok, up till now no problem.

Doing this exercise, I remembered to had read before that rspeck doubles framework could be used inside cucumber, so I thought I could clean it a little bit.

First, I have included rspeck doubles framework in support/env.rb:

require 'cucumber/rspec/doubles'

And then I have changed the step definitions:

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

The strange think is that now, when I execute the feature with cucumber, in the summary I get all 4 steps passing but not the whole scenario. How is it possible? What is it happening? Here it is the output I get from the command line:

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

回答1:


When you set an expectation like should_receive, you're specifying that a some point in the future the specified method should be called - anything that has happened previously is ignored (or else it would be should have_received or something like that in the past tense).

In your code you're setting up the expectation in your Then step but the method gets called in your When step (i.e. before), so at that point no expectation has been setup. Your double is setup to allow any method to be called, so you get no errors, but when spec checks at the end whether all expectations have been satisfied it will say no and raise an exception



来源:https://stackoverflow.com/questions/10795854/cucumber-test-double-scenario-failing-but-its-steps-passing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!