【问题标题】:When using factory_bot (formerly factory_girl) with RSpec to test in Rails, undefined method "first"在使用带有 RSpec 的 factory_bot(原 factory_girl)在 Rails 中进行测试时,未定义方法“first”
【发布时间】:2017-10-23 07:03:44
【问题描述】:

我有一个使用 factory_bot 创建实例的 RSpec 测试。测试通过,除非在视图中使用 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 方法本身的问题,而是当我运行 RSpec 时视图中的插值 Ruby 引发错误。这概括了问题,并希望使其更容易解决。

【问题讨论】:

  • 您的订单类型为integer,所以我认为您的工厂有问题。您没有包括 base_item 工厂。当您执行order = create(:base_item) 时,您必须有一个工厂来定义base_item,我需要看到它。
  • 我已经在上面添加了相关的工厂文件。
  • orderConfirmationMail vs order_confirm_email,是哪个?
  • @SergioTulentsev,这不是问题,因为在前面的规范中我包含了我知道工作正常的这一行,因为我在另一个测试中成功使用了相同的格式:let(:orderConfirmationMail) { UserMailer.order_confirm_email(1,2,3,4,nil) }。

标签: ruby-on-rails ruby rspec factory-bot


【解决方案1】:

这不是问题,因为在前面的规范中我包含了我知道工作正常的这一行,因为我在另一个测试中成功使用了相同的格式

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? 因为你是这样通过的!

谜团解开了。

【讨论】:

  • @223seneca 不错。现在我也明白了。他没有使用工厂,而是通过调用方法UserMailer.order_confirm_email(1,2,3,4,nil) 设置实例变量@order,从而设置@order = 3。你解决了塞尔吉奥的问题。我相信@223seneca 应该接受您的回答作为正确的解决方案。
  • 这确实回答了我所说的问题,所以我会接受作为解决方案。我的工厂似乎存在一个更深层次的问题,我现在需要解决这个问题。任何问题都将作为一个单独的问题发布。
  • @223seneca:你们的工厂运转良好,我敢打赌。你只是不使用构建的对象。
  • @SergioTulentsev:我当然希望是这样。如果您不介意进一步帮助我,我该如何正确访问这些构建对象?这是我第一次同时使用 RSpec 和 factory_bot,我正在处理一些从不再在我们公司的开发人员那里继承的代码,所以我边走边学。
  • @223seneca:将它们提取到let 块中。在这里查看第一个绿色示例:betterspecs.org/#let 通读全文,它非常有用。
【解决方案2】:

对不起,我不知道。我会看看你的 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不是我们所期望的

但你可以通过在你工厂的控制台中调试和测试来理解这一点

【讨论】:

  • 我尝试在控制台中调试,但无法确定问题的根源。更新 2 是否为您提供了更多有用的背景信息?
  • @223seneca 你的问题解决了。 Sergio Tulentsev 解决了这个问题。如果您有其他问题,您可以打开一个新问题。此外,您需要接受 Sergio 的回答,因为我阅读了它,它是您问题的解决方案
  • @FabrizioBertoglio:这不是一个“解决方案”,它只是指出问题的根源:)
  • @SergioTulentsev 他从标题When using factory_bot (formerly factory_girl) with RSpec to test in Rails, undefined method “first” 定义的问题得到了解决。现在显示另一条错误消息,但我认为他应该写一个新问题并包含该问题的所有相关信息。
猜你喜欢
  • 2013-04-08
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2013-07-31
  • 1970-01-01
相关资源
最近更新 更多