【问题标题】:RSpec - how to fix - ArgumentError: wrong number of arguments (given 0, expected 1) - RubyRSpec - 如何修复 - ArgumentError:参数数量错误(给定 0,预期为 1) - Ruby
【发布时间】:2020-06-07 00:18:42
【问题描述】:

我是学习 RSpec 的新手。我似乎无法理解为什么我的测试 #start method 失败了。

如果有人能给我解释一下,将不胜感激。

我得到的错误:

CardGame
  attributes
    should have a name
  #response method
    should say hello
  #start method
    can only implement class methods that are defined on a class (FAILED - 1)

Failures:

  1) CardGame#start method can only implement class methods that are defined on a class
     Failure/Error:
       def initialize(name)
         @name = name
       end
     
     ArgumentError:
       wrong number of arguments (given 0, expected 1)
     # ./lib/CardGame.rb:4:in `initialize'
     # ./spec/class_double_spec.rb:29:in `block (3 levels) in <top (required)>'

Finished in 0.01178 seconds (files took 0.30252 seconds to load)
3 examples, 1 failure

Failed examples:

rspec ./spec/class_double_spec.rb:27 # CardGame#start method can only implement class methods that are defined on a class

➜  rspec-course 

class_double_spec.rb

[ruby/spec/class_double_spec.rb]

    require 'spec_helper'
    require 'pry'
    require './lib/CardGame'
    require './lib/Deck'
    
    describe CardGame do
      let(:card) { instance_double(CardGame, 
                                  name: 'poker',
                                  response: 'hello')} 
      let(:deck_klass) { class_double(Deck, build: ['Ace', 'Queen']).as_stubbed_const }
    
      context 'attributes' do
        it 'should have a name' do
          expect(card.name).to eq('poker')
        end
      end
    
      context '#response method' do
        it 'should say hello' do
          allow(card).to receive(:response).and_return('hello')
          expect(card.response).to eq('hello')
        end
      end
    
      context '#start method' do
        it 'can only implement class methods that are defined on a class' do
          expect(deck_klass).to receive(:build)
          card.start
          expect(card.cards).to eq(['Ace', 'Queen'])
        end
      end
    end 

CardGame.rb

[ruby/lib/CardGame.rb]

    class CardGame
      attr_accessor :name, :cards
    
      def initialize(name)
        @name = name
      end
    
      def response
        'hello'
      end
    
      def start
        @cards = Deck.build
      end
    end

甲板.rb

[ruby/lib/Deck.rb]

    class Deck
      def self.build
        # business logic to build cards
      end
    end

【问题讨论】:

  • 您使用什么版本的 RSpec?当我运行您的代码时,我收到其他错误`# received unexpected message :start with (no args)`。 Rspec 3.9

标签: ruby rspec tdd


【解决方案1】:

你嘲笑嘲笑。应该严格应用的规则之一是不要模拟被测单元,所以不要模拟

describe CardGame do
      let(:card) { instance_double(CardGame, 
                                  name: 'poker',
                                  response: 'hello')} 
      let(:deck_klass) { class_double(Deck, build: ['Ace', 'Queen']).as_stubbed_const }

      context 'attributes' do
        it 'should have a name' do
          expect(card.name).to eq('poker')
        end
      end
end

这样做

describe CardGame do
      let(:card) { CardGame.new(name) }
      let(:name) { 'poker'}

      context 'attributes' do
        it 'should have a name' do
          expect(card.name).to eq('poker')
        end
      end
end

为什么不应该模拟被测单元?

      context '#response method' do
        it 'should say hello' do
          allow(card).to receive(:response).and_return('hello')
          expect(card.response).to eq('hello')
        end
      end

因为在示例中您只是测试 RSpec 的模拟框架是否有效。简化它

      context '#response method' do
        it 'should say hello' do
          expect(card.response).to eq('hello')
        end
      end

最后一个例子:

      context '#start method' do
        it 'can only implement class methods that are defined on a class' do
          expect(deck_klass).to receive(:build)
          card.start
          expect(card.cards).to eq(['Ace', 'Queen'])
        end
      end

看起来更好,模拟类没有直接测试,而是被测试单元使用(Card)。

如果您正在学习 RSpec - 尝试尽可能少地模拟。这将迫使你设计你的类,以便它们易于测试。现在你正在以你以前习惯的方式设计它,这使得课程很难测试,这迫使你使用模拟(而且因为你只是在学习 - 很容易找不到你不测试任何东西的地方)

【讨论】:

  • 乐于助人 :) 祝你好运。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多