编写 rspec 测试以将项目添加到哈希
writing a rspec test to add an item to a hash
我收到一个 NoMethodError
对于我的代码,但我已经定义了它说缺少的添加方法。
我正在尝试将一个项目添加到已经存在的散列中。
散列是菜肴,我正在尝试使用 add 方法。
测试:
require 'menu'
describe Menu do
it 'has a menu' do
expect(subject.respond_to?(:dishes)).to be true
end
it 'displays dishes and prices' do
expect(subject.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
it 'can add dishes to it' do
menu = Menu.new
menu.add_dish("Icecream", 4.80)
expect(subject.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 },
{ name: 'icecream', price: 4.80 }
]
end
end
方法
class Menu
def initialize
@dishes = []
end
def dishes
@dishes = [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
def add_dish(name, price)
@dishes << { name: name, price: price }
end
end
谢谢
啊,我明白你的问题了。您需要初始化菜单。 Add
不是静态方法。所以你需要类似的东西,
Menu.new.add(blah, blah)
查看:
Menu.add("Icecream", 4.80)
这个方法是错误的。必须是:
Menu.new.add("Icecream", 4.80)
或者您需要类似的东西:
menu = Menu.new
menu.add("Icecream", 4.80)
如果没有你的代码,要让它工作有点困难,但问题很简单。
试试下面编辑过的代码。请注意对规范的更改初始化菜单并将添加方法添加到实例变量@dishes.
require 'menu'
describe Menu do
it 'displays dishes and prices' do
expect(Menu.new.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
it 'can add dishes to it' do
menu = Menu.new.add("Icecream", 4.80)
expect(menu.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 },
{ name: 'icecream', price: 4.80 }
]
end
end
class Menu
def initialize
@dishes = []
end
def dishes
@dishes ||=
[
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
def add(name, price)
@dishes << { name: name, price: price }
end
end
希望对您有所帮助
看起来您在使用这段代码时遇到了一些问题。首先,因为 add
方法没有声明为 class 方法(即 def self.add
),所以不能将其作为 class 方法调用(如您所见, Menu.add
表示 NoMethodError)。相反,您需要在测试中创建菜单 class 的实例,也许使用 let
:
describe Menu do
let(:menu) { Menu.new }
it 'can add dishes to it' do
menu.add("Icecream", 4.80)
# test your expectations...
end
end
最后,由于 add
方法是当前定义的,它不会修改 @dishes
而只是 returns 一个新的散列,所以你的期望会失败。您需要使 add
方法附加值,可能像这样:
def add(name, , price)
@dishes << {name: name, price: price}
end
的回答解决了NoMethodError,但是你的代码还有很多其他的问题
重复你自己,你应该让你的代码变干(Don't Repeat Yourself原则)
当您想要将散列添加到本身就是散列列表的菜肴列表时,您强制需要调用 add 方法的对象以特定顺序提供参数, 而不是该方法构造哈希,因此每次需要调用它时,您都需要 return 以查看参数的顺序。
dishes
方法是错误的,因为每次调用它时,它都会将初始数组赋值给@dishes
变量。在这种情况下,add_dishes
方法将无效,因为添加的菜肴将在您下次调用 dishes
方法时被删除。
- 你的例子没有表现力,所以如果测试没有通过,你无法从打印的消息中知道问题出在哪里。 OK,在这个小例子中这没什么大不了的,但是在一个大的应用程序中,specs expressiveness 具有更高的价值。
这里是测试例子
require 'menu'
describe Menu do
# every time you call the function dishes in an example
# it will be declared and it will return this array
let :dishes do
[
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
# explicit definition of the subject
subject { Menu.new }
# a shorter yet more expressive version of
# expect(subject.respond_to?(:dishes)).to be true
it { is_expected.to respond_to(:dishes) }
# You should always group the examples that test
# the same method
describe '#dishes' do
# it 'displays dishes and prices' do
it 'returns the list of dishes' do
expect(subject.dishes).to eq dishes
end
end
describe "#add_dish" do
# it 'can add dishes to it' do
it "adds the given dish to the list of dishes" do
new_dish = {name: 'salad', price: 4.0 }
expect {
subject.add_dish(new_dish)
}.to change(subject.dishes, :count).by(1)
expect(subject.dishes).to include new_dish
end
end
end
所以这是 class 定义
class Menu
# you don't need to declare the method dishes
# since this is what attr_reader will do
attr_reader :dishes
def initialize
# this will set the @dishes only once
# but you code @dishes = [...] will return
# the same list every time you call it and
# all the dishes you add through the #add method
# will be deleted.
@dishes = [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
# dish is a hash {name: '', price: ''}
def add_dish(dish)
@dishes << dish
end
end
所以现在 运行 rspec --format doc --color
看看谁表达了这些信息。
我收到一个 NoMethodError 对于我的代码,但我已经定义了它说缺少的添加方法。 我正在尝试将一个项目添加到已经存在的散列中。 散列是菜肴,我正在尝试使用 add 方法。
测试:
require 'menu'
describe Menu do
it 'has a menu' do
expect(subject.respond_to?(:dishes)).to be true
end
it 'displays dishes and prices' do
expect(subject.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
it 'can add dishes to it' do
menu = Menu.new
menu.add_dish("Icecream", 4.80)
expect(subject.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 },
{ name: 'icecream', price: 4.80 }
]
end
end
方法
class Menu
def initialize
@dishes = []
end
def dishes
@dishes = [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
def add_dish(name, price)
@dishes << { name: name, price: price }
end
end
谢谢
啊,我明白你的问题了。您需要初始化菜单。 Add
不是静态方法。所以你需要类似的东西,
Menu.new.add(blah, blah)
查看:
Menu.add("Icecream", 4.80)
这个方法是错误的。必须是:
Menu.new.add("Icecream", 4.80)
或者您需要类似的东西:
menu = Menu.new
menu.add("Icecream", 4.80)
如果没有你的代码,要让它工作有点困难,但问题很简单。
试试下面编辑过的代码。请注意对规范的更改初始化菜单并将添加方法添加到实例变量@dishes.
require 'menu'
describe Menu do
it 'displays dishes and prices' do
expect(Menu.new.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
it 'can add dishes to it' do
menu = Menu.new.add("Icecream", 4.80)
expect(menu.dishes).to eq [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 },
{ name: 'icecream', price: 4.80 }
]
end
end
class Menu
def initialize
@dishes = []
end
def dishes
@dishes ||=
[
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
def add(name, price)
@dishes << { name: name, price: price }
end
end
希望对您有所帮助
看起来您在使用这段代码时遇到了一些问题。首先,因为 add
方法没有声明为 class 方法(即 def self.add
),所以不能将其作为 class 方法调用(如您所见, Menu.add
表示 NoMethodError)。相反,您需要在测试中创建菜单 class 的实例,也许使用 let
:
describe Menu do
let(:menu) { Menu.new }
it 'can add dishes to it' do
menu.add("Icecream", 4.80)
# test your expectations...
end
end
最后,由于 add
方法是当前定义的,它不会修改 @dishes
而只是 returns 一个新的散列,所以你的期望会失败。您需要使 add
方法附加值,可能像这样:
def add(name, , price)
@dishes << {name: name, price: price}
end
重复你自己,你应该让你的代码变干(Don't Repeat Yourself原则)
当您想要将散列添加到本身就是散列列表的菜肴列表时,您强制需要调用 add 方法的对象以特定顺序提供参数, 而不是该方法构造哈希,因此每次需要调用它时,您都需要 return 以查看参数的顺序。
dishes
方法是错误的,因为每次调用它时,它都会将初始数组赋值给@dishes
变量。在这种情况下,add_dishes
方法将无效,因为添加的菜肴将在您下次调用dishes
方法时被删除。- 你的例子没有表现力,所以如果测试没有通过,你无法从打印的消息中知道问题出在哪里。 OK,在这个小例子中这没什么大不了的,但是在一个大的应用程序中,specs expressiveness 具有更高的价值。
这里是测试例子
require 'menu'
describe Menu do
# every time you call the function dishes in an example
# it will be declared and it will return this array
let :dishes do
[
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
# explicit definition of the subject
subject { Menu.new }
# a shorter yet more expressive version of
# expect(subject.respond_to?(:dishes)).to be true
it { is_expected.to respond_to(:dishes) }
# You should always group the examples that test
# the same method
describe '#dishes' do
# it 'displays dishes and prices' do
it 'returns the list of dishes' do
expect(subject.dishes).to eq dishes
end
end
describe "#add_dish" do
# it 'can add dishes to it' do
it "adds the given dish to the list of dishes" do
new_dish = {name: 'salad', price: 4.0 }
expect {
subject.add_dish(new_dish)
}.to change(subject.dishes, :count).by(1)
expect(subject.dishes).to include new_dish
end
end
end
所以这是 class 定义
class Menu
# you don't need to declare the method dishes
# since this is what attr_reader will do
attr_reader :dishes
def initialize
# this will set the @dishes only once
# but you code @dishes = [...] will return
# the same list every time you call it and
# all the dishes you add through the #add method
# will be deleted.
@dishes = [
{ name: 'Burger', price: 10.95 },
{ name: 'Pizza', price: 14.00 },
{ name: 'Salad', price: 7.60 },
{ name: 'fries', price: 2.90 }
]
end
# dish is a hash {name: '', price: ''}
def add_dish(dish)
@dishes << dish
end
end
所以现在 运行 rspec --format doc --color
看看谁表达了这些信息。