RSpec-如何修复-ArgumentError:参数数量错误(给定0,应为1)-Ruby



我是学习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

你一个模拟一个模拟。一个人应该严格应用的规则之一是不要模拟测试中的单元,所以代替

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的mocking框架是否有效。简化

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——试着尽可能少地嘲笑。这将迫使你设计你的类,使它们易于测试。现在你正在用你以前习惯的方式设计它,这使得课程很难测试,这迫使你使用模拟(因为你只是在学习——很容易找不到你什么都不测试的地方(

最新更新