[英]RSpec - how to fix - ArgumentError: wrong number of arguments (given 0, expected 1) - Ruby
I'm new to learning RSpec.我是学习 RSpec 的新手。 I can't seem to understand why my test
#start method
is failing.我似乎无法理解为什么我的测试
#start method
失败。
would be grateful if one could explain to me.如果有人能向我解释,将不胜感激。
the error i am getting:我得到的错误:
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 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
Deck.rb甲板.rb
[ruby/lib/Deck.rb]
class Deck
def self.build
# business logic to build cards
end
end
You mock to mock.你嘲笑嘲笑。 One of the rules one should strictly apply is not to mock unit under test, so instead of
应该严格应用的规则之一是不要模拟被测单元,因此而不是
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
do this做这个
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
Why should you not mock the unit under test?为什么不模拟被测单元?
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
Because in the example you're only testing that the RSpec's mocking framework works.因为在示例中,您只是在测试 RSpec 的模拟框架是否有效。 Simplify it
简化它
context '#response method' do
it 'should say hello' do
expect(card.response).to eq('hello')
end
end
The last example:最后一个例子:
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
Looks better, the mocked class is not directly tested, but used by the unit under test ( Card
).看起来更好,模拟类没有直接测试,而是由被测单元(
Card
)使用。
If you're learning RSpec - try to mock as little as possible.如果您正在学习 RSpec - 尝试尽可能少地模拟。 This will force you to design your classes so they're easy to test.
这将迫使您设计类,以便它们易于测试。 Right now you're designing it in your old habitual way, that makes the class hard to test, which forces you to use mocks (and since you're just learning - it's easy to not spot the placec where you don't test anything)
现在您正在以旧的习惯方式设计它,这使得课程难以测试,这迫使您使用模拟(并且因为您只是在学习 - 很容易找不到您不测试任何东西的地方)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.