当使用 factory_bot(以前的 factory_girl)和 RSpec 在 Rails 中进行测试时,未定义的方法 "first"
When using factory_bot (formerly factory_girl) with RSpec to test in Rails, undefined method "first"
我有一个 RSpec 测试,它使用 factory_bot 创建实例。测试通过,除非在视图中使用 first 方法。
这是正在测试的代码:
def order_confirm_email(id, items, order, address, coupon)
@user = User.find(id)
@items = items
@order = order
@address = address
if coupon == nil
@coupon = ''
else
@coupon = coupon.discount
end
mail(to: @user.email, subject: 'Order completed')
end
这是测试:
it 'sends an email upon checkout process completion' do
user = create(:user)
items = create(:base_item)
order = create(:base_item)
address = create(:address)
coupon = create(:coupon)
expect(orderConfirmationMail.subject).to eq('Order completed')
end
到目前为止一切顺利。但是当其中一个视图尝试访问第一个实例时,如下所示:
<h1>Order id - <%= @order.first.id %></h1>
然后我收到以下错误:
Failures:
1) UserMailer user_emails sends an email upon checkout process completion
Failure/Error: <!-- <h1>Order id - <%= @order.first.id %></h1> -->
ActionView::Template::Error:
undefined method `first' for 3:Fixnum
根据我的理解,实例应该是持久的,因为我使用 create 而不是 build。但显然这并没有发生。除非万不得已,否则不得更改视图。我该如何解决?
更新 1:
这是order_items.rb工厂文件:
FactoryBot.define do
factory :base_item, class: OrderItem do
item_name_en "Sample Item"
item_link "http://www.foo.com"
qty 5
available_qty 100
item_price 10
seller_name "foo"
status "foo"
foo_item_id "123456"
foo_id "654321"
end
factory :order_item1, parent: :base_item do
foo_item_id "123456"
foo_seller_id "654321"
association :order
end
factory :order_item2, parent: :base_item do
foo_item_id "123457"
foo_seller_id "654321"
end
factory :order_item3, parent: :base_item do
foo_item_id "123458"
foo_seller_id "654322"
end
end
更新 2:
我在编写另一个测试时遇到了类似的问题。我收到以下错误:
Failures:
1) UserMailer user_emails sends an email upon abandoned cart
Failure/Error: <% @items.each do |item| %>
ActionView::Template::Error:
undefined method `each' for 1:Fixnum
这似乎表明这不是 first 方法本身的问题,而是视图中的插值 Ruby 在我抛出错误时运行 RSpec。这概括了问题,并希望使其更容易解决。
抱歉,我不知道。我会看看你的 OrderItem
模型,我也不明白你为什么要 @order.first
因为那只是 1 个对象。对我来说可能有意义 @orders.first
但对 @order.first
没有意义。当事情在 rails
中没有意义时,就很难构建应用程序。 order
和 item
应该是两个不同的模型,我们使用 order_items
来建立两个不同模型之间的连接
一个订单可以有很多,也可以只有一个,关系由你决定。
使用rspec
你可以在rails c test
环境中调试和测试你的工厂。在那里你可以检查 create(:base_item)
或 FactoryGirl.create(:base_item)
的结果是什么
我认为那应该是一个对象,所以我不明白为什么它说 undefined method 'first' for 3:Fixnum
也许你factory
并不是我们所期待的
但你可以通过在你的工厂的控制台中调试和测试来理解这一点
that is not an issue, as earlier in the spec I include this line that I know is working correctly because I use the same format in another test successfully
let(:orderConfirmationMail) { UserMailer.order_confirm_email(1,2,3,4,nil) }
就是这样。如果您从一开始就包括这一行,您的问题将在两秒钟内得到解答。
正在考虑 order_confirm_email
的签名
def order_confirm_email(id, items, order, address, coupon)
为什么您认为 order
设置为 3? 因为你是这样传递的!
谜团解开了。
我有一个 RSpec 测试,它使用 factory_bot 创建实例。测试通过,除非在视图中使用 first 方法。
这是正在测试的代码:
def order_confirm_email(id, items, order, address, coupon)
@user = User.find(id)
@items = items
@order = order
@address = address
if coupon == nil
@coupon = ''
else
@coupon = coupon.discount
end
mail(to: @user.email, subject: 'Order completed')
end
这是测试:
it 'sends an email upon checkout process completion' do
user = create(:user)
items = create(:base_item)
order = create(:base_item)
address = create(:address)
coupon = create(:coupon)
expect(orderConfirmationMail.subject).to eq('Order completed')
end
到目前为止一切顺利。但是当其中一个视图尝试访问第一个实例时,如下所示:
<h1>Order id - <%= @order.first.id %></h1>
然后我收到以下错误:
Failures:
1) UserMailer user_emails sends an email upon checkout process completion
Failure/Error: <!-- <h1>Order id - <%= @order.first.id %></h1> -->
ActionView::Template::Error:
undefined method `first' for 3:Fixnum
根据我的理解,实例应该是持久的,因为我使用 create 而不是 build。但显然这并没有发生。除非万不得已,否则不得更改视图。我该如何解决?
更新 1:
这是order_items.rb工厂文件:
FactoryBot.define do
factory :base_item, class: OrderItem do
item_name_en "Sample Item"
item_link "http://www.foo.com"
qty 5
available_qty 100
item_price 10
seller_name "foo"
status "foo"
foo_item_id "123456"
foo_id "654321"
end
factory :order_item1, parent: :base_item do
foo_item_id "123456"
foo_seller_id "654321"
association :order
end
factory :order_item2, parent: :base_item do
foo_item_id "123457"
foo_seller_id "654321"
end
factory :order_item3, parent: :base_item do
foo_item_id "123458"
foo_seller_id "654322"
end
end
更新 2:
我在编写另一个测试时遇到了类似的问题。我收到以下错误:
Failures:
1) UserMailer user_emails sends an email upon abandoned cart
Failure/Error: <% @items.each do |item| %>
ActionView::Template::Error:
undefined method `each' for 1:Fixnum
这似乎表明这不是 first 方法本身的问题,而是视图中的插值 Ruby 在我抛出错误时运行 RSpec。这概括了问题,并希望使其更容易解决。
抱歉,我不知道。我会看看你的 OrderItem
模型,我也不明白你为什么要 @order.first
因为那只是 1 个对象。对我来说可能有意义 @orders.first
但对 @order.first
没有意义。当事情在 rails
中没有意义时,就很难构建应用程序。 order
和 item
应该是两个不同的模型,我们使用 order_items
来建立两个不同模型之间的连接
一个订单可以有很多,也可以只有一个,关系由你决定。
使用rspec
你可以在rails c test
环境中调试和测试你的工厂。在那里你可以检查 create(:base_item)
或 FactoryGirl.create(:base_item)
我认为那应该是一个对象,所以我不明白为什么它说 undefined method 'first' for 3:Fixnum
也许你factory
并不是我们所期待的
但你可以通过在你的工厂的控制台中调试和测试来理解这一点
that is not an issue, as earlier in the spec I include this line that I know is working correctly because I use the same format in another test successfully
let(:orderConfirmationMail) { UserMailer.order_confirm_email(1,2,3,4,nil) }
就是这样。如果您从一开始就包括这一行,您的问题将在两秒钟内得到解答。
正在考虑 order_confirm_email
def order_confirm_email(id, items, order, address, coupon)
为什么您认为 order
设置为 3? 因为你是这样传递的!
谜团解开了。