0

Card、Deck、Hand、Player、および Game クラスを使用してポーカー ゲームを作成するために、RSpec を初めて使用しています。カード、デッキ、ハンドのテスト/クラスを完了しました。現在、プレイヤーのテスト/クラスを作成しています。依存関係が大きくなるにつれてモック/スタブに依存することが難しくなり、RSpec がこのエラーをスローしているため、Player#discard メソッドのテストでエラーがスローされるという問題に直面しています。

1) Player#discard discards the chosen card
   Failure/Error: player.discard
      Double "hand" received unexpected message :delete_if with (no args)
    # ./lib/player.rb:19:in `block in discard'
    # ./lib/player.rb:18:in `each'
    # ./lib/player.rb:18:in `discard'
    # ./spec/player_spec.rb:34:in `block (3 levels) in <top (required)>'

私はRSpecが初めてで、何が間違っているのかよくわかりません。私の仕様で実際のクラスオブジェクトを使用してそれらを通過させないようにする方法についてのヘルプとアドバイスをいただければ幸いです。これまでのところ、私の player_spec と Player クラスは次のとおりです。

./spec/player_spec.rb

require 'rspec'
require 'player'

describe Player do
  subject(:player) { Player.new }

  its(:hand) { double("hand", :cards => []) }
  its(:pot)  { should eq 1000 }

  let(:ace_spades)    { double("card", :suit => :spades, :value => :ace) }
  let(:ace_clubs)     { double("card", :suit => :clubs, :value => :ace) }
  let(:king_spades)   { double("card", :suit => :spades, :value => :king) }
  let(:king_clubs)    { double("card", :suit => :clubs, :value => :king) }
  let(:queen_spades)  { double("card", :suit => :spades, :value => :queen) }
  let(:queen_clubs)   { double("card", :suit => :clubs, :value => :queen) }
  let(:jack_spades)   { double("card", :suit => :spades, :value => :jack) }
  let(:jack_clubs)    { double("card", :suit => :clubs, :value => :jack) }
  let(:ten_spades)    { double("card", :suit => :spades, :value => :ten) }
  let(:ten_clubs)     { double("card", :suit => :clubs, :value => :ten) }
  let(:nine_spades)   { double("card", :suit => :spades, :value => :nine) }
  let(:nine_hearts)   { double("card", :suit => :hearts, :value => :nine) }
  let(:nine_clubs)    { double("card", :suit => :clubs, :value => :nine) }
  let(:nine_diamonds) { double("card", :suit => :diamonds, :value => :nine) }

  let(:discard_hand)  do 
    double("hand", :cards => [nine_clubs, ace_spades, nine_hearts, ten_clubs, ten_spades])
  end
  let(:discard_input) { ["A","S"] }

  describe "#discard" do
    it "discards the chosen card" do
      player.hand.stub(:cards).and_return(discard_hand)
      player.stub(:get_input).and_return(discard_input)
      player.discard
      expect(player.hand.cards).to eq([nine_clubs, nine_hearts, ten_clubs, ten_spades])
    end
  end
end

./lib/player.rb

class Player
  INPUT_VALUES = { "2" => :deuce, "3" => :three, "4" => :four, 
               "5" => :five, "6" => :six, "7" => :seven, 
               "8" => :eight, "9" => :nine, "10" => :ten, 
               "J" => :jack, "Q" => :queen, "K" => :king, "A" => :ace }
  INPUT_SUITS  = { "S" => :spades, "H" => :hearts, "C" => :clubs, "D" => :diamonds }

  attr_accessor :pot, :hand

  def initialize
    @pot  = 1000
    @hand = Hand.new
  end

  def discard
    discards = get_input("Which card(s) would you like to discard?:")

    discards.each do |discard|
      self.hand.cards.delete_if do |card| 
        card.value == discard[0] && card.suit == discard[1]
      end
   end
 end

private

  def get_input(prompt)
    puts prompt
    input = gets.chomp
    parse_input(input)
  end

  def parse_input(input)
    value = input.scan(/^(?:[2-9]|10|[jqkaJQKA])/)
    suit = input.scan(/[shdcSHDC]$/)
    raise "Invalid Input" if values.empty? || suit.empty?

    (value[0].match(/[jqkaJQKA]/)) ? value[0].upcase! : value.map!(&:to_i)
    suit[0].upcase!

    value = INPUT_VALUES[value[0]]
    suit  = INPUT_SUITS[suit[0]]

    [value, suit]
  end
end
4

1 に答える 1

1

呼び出しているコード (つまりdiscard) がdelete_if、それを許可する期待を設定していない double の 1 つを呼び出しているため、エラーが発生しています。stub_chainこれを達成する手段としてチェックアウトする必要があります。

ただし、より一般的には、に委譲するPlayerのではなく、直接cards配列を操作して削除機能を実装するようにdiscardメソッドに要求しているため、問題が発生していると思います。コードを単純化できれば、テストも単純化されます。discardHand

于 2013-11-02T19:36:19.497 に答える