【问题标题】:Account for instance variable set by session value in controller说明由控制器中的会话值设置的实例变量
【发布时间】:2014-06-10 22:40:31
【问题描述】:

我正在尝试在控制器中测试“创建后”操作。在“创建”期间,在控制器中,我分配了一个变量,其值会在保存新记录之前修改该记录。 @trip 这个变量是从我似乎无法解释的会话值创建的。

所以我的问题是,鉴于我要测试的内容,当控制器中的实例变量由会话值设置时,说明该变量的最佳方式(或任何方式)是什么?

错误信息:

OrderItemsController POST create with valid attributes creates a new order item
Failure/Error: expect{ post :create, order_item: FactoryGirl.attributes_for(:order_item) }.to change(OrderItem,:count).by(1)
NoMethodError:
       undefined method `company_id' for nil:NilClass
 # ./app/controllers/order_items_controller.rb:29:in `create'
 # ./spec/controllers/order_items_controller_spec.rb:47:in `block (4 levels) in <top (required)>'

控制器规格:

describe "POST create action" do
    let(:trip)              { create(:trip)}
    let(:trip_date)         { create(:trip_date) }
    let(:buyer)             { create(:buyer) }
    let(:company)           { create(:company) }
    let(:order_item)        { attributes_for(:order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }
    let(:bad_order_item)    { attributes_for(:bad_order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }

    context "given valid order item attributes" do
        it "creates a new order item" do
            expect{ post :create, { order_item: order_item, trip_id: trip.id } }.to change(OrderItem, :count).by(1)
        end
    end
end

错误引用了我的 order_items_controller.rb 的第 29 行,变量所在的位置:

line 25:    def create
line 26:        @trip = Trip.find_by_id(session[:current_trip_id])
line 27:        @order_item = OrderItem.new(order_item_params)
line 28:        @order_item.buyer_id            = current_user.id
> line 29:      @order_item.company_id          = @trip.company_id
line 30:        @order_item.first_person_cost   = @trip.first_person_cost
line 31:        @order_item.second_person_cost  = @trip.second_person_cost

line 32:        if @order_item.save
line 33:            redirect_to cart_path(current_user), notice: 'New order item created.'
line 34:        else
line 35:            render 'new', notice: 'Unable to create new order item.'
line 36:        end    
line 37:    end  

其他尝试

b.我也试过:

    let(:trip_date)         { create(:trip_date) }
    let(:buyer)             { create(:buyer) }
    let(:company)           { create(:company) }
    let(:order_item)        { attributes_for(:order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }
    let(:bad_order_item)    { attributes_for(:bad_order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }

    describe "POST create" do
        let(:trip)     {create(:trip) }
        context "with valid attributes" do
            it "creates a new order item" do
              Trip.stub_chain(:friendly, :find_by_id).and_return(trip)
              expect{ post :create, order_item: order_item }.to change(OrderItem,:count).by(1)
              end
          end
        end
    end

导致同样的错误。

c。我也试过了

describe "POST create action" do
    let(:trip)              { create(:trip) }
    let(:trip_date)         { create(:trip_date) }
    let(:buyer)             { create(:buyer) }
    let(:company)           { create(:company) }
    let(:order_item)        { attributes_for(:order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }
    let(:bad_order_item)    { attributes_for(:bad_order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }

    context "given valid order item attributes" do
        it "creates a new order item" do
            expect{ post :create, order_item: order_item, trip_id: trip.id }.to change(OrderItem, :count).by(1)
        end
    end
end

导致同样的错误。

d。我也试过:

    describe "POST create action" do
        let(:trip_date)         { create(:trip_date) }
        let(:buyer)             { create(:buyer) }
        let(:company)           { create(:company) }
        let(:bad_order_item)    { attributes_for(:bad_order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }

        context "given valid order item attributes" do
            it "creates a new order item" do
            Trip.stub_chain(:friendly, :find_by_id).and_return(trip)
            order_item = attributes_for(:order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id)
            expect{ post :create, order_item: order_item }.to change(OrderItem, :count).by(1)
        end
    end

导致:

1) OrderItemsController POST create action given valid order item attributes creates a new order item
    Failure/Error: Trip.stub_chain(:friendly, :find_by_id).and_return(trip)
    NameError:
        undefined local variable or method `trip' for #<RSpec::ExampleGroups::OrderItemsController_2::POSTCreateAction::GivenValidOrderItemAttributes:0x0000010154d5d8>
        # ./spec/controllers/order_items_controller_spec.rb:41:in `block (4 levels) in <top (required)>'

感谢任何帮助。已经有几个星期了。谢谢。

【问题讨论】:

  • 缺少第 26 行]。毫无疑问,它在原版中。 d 只是因为您没有在测试中定义行程。我会从你的问题中删除那个。其余的,您需要调试。在控制器中放置日志记录或断点以查看 params[:trip_id]Trip.friendly 是什么,也许你会学到一些东西。
  • 对不起,我不太明白。第 26 行是我在测试中无法解释的。你说的失踪就是这个意思吗?你是说我除了 d 之外的尝试一般都在正确的轨道上?
  • 在第 26 行,:trip_id 后面应该跟 ]
  • 知道了。你其实说的很清楚。修正了示例错字。
  • 意识到我的问题不包括从会话中提取变量的事实。已更新。

标签: ruby-on-rails ruby-on-rails-4 rspec rspec3


【解决方案1】:

我终于在谷歌上搜索了正确的术语,并找到了讨论如何为每个操作设置会话变量的 Rails 文档。我的解决方案如下所示:

expect{ post :create, {order_item: order_item}, {"current_trip_id" => trip.id}  }.to change(OrderItem, :count).by(1)

我的救赎就在这里:http://guides.rubyonrails.org/testing.html

【讨论】:

    【解决方案2】:
    expect{ post :create, order_item: order_item, trip_id: trip.id }
    

    尝试将其更改为:

    expect{ post :create, { order_item: order_item, trip_id: trip.id } }
    

    post 将参数哈希和会话哈希作为参数;所有发布的参数都应该在一个哈希中。

    【讨论】:

    • 我已更改代码以匹配,但没有骰子。我已经更新了我的代码以显示我在这次尝试中使用的内容(尝试 c,上面)
    • 这两行的行为相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    相关资源
    最近更新 更多