2017-05-30 61 views
0

在特定的测试中,我想从我的站点的某些订单中添加多个项目(package_sets)。RSpec保留发布请求之间的实例变量

为了测试它,我做如下

context "with multiple package sets from different shops" do 

    let(:package_sets) { FactoryGirl.create_list(:package_set, 3) } 

    it "adds package sets to multiple orders" do 
     package_sets.each do |package_set| 
     post :create, {'package_set_id': package_set.id} 
     expect_json(success: true) 
     end 
     expect(Order.count).to eq(3) 
    end 

    end 

在现实世界中,每一个我称之为post :create将分配包设置为不同的顺序时间;订单的总数应为3

在我控制我memoize的顺序的方法中这样

def order 
    @order ||= cart_manager.order(shop: package_set.shop, call_api: false) 
end 

因为它是3个不同的要求,我期待测试过加载此方法,无需记忆化,但它保持在post请求之间的记忆,这使得测试失败。

你如何预防这种情况?

回答

1

这里发生的是RSpec不会在您的示例中创建新的控制器实例;你可以通过泄露一些逻辑到你的测试解决这个问题:

controller.instance_variable_set(:@order, nil) 

也许码缩短为这个特殊的问题,但你会考虑一个单一的动作测试控制器?

package_set = FactoryGirl.create(:package_set) 
expect do 
    post :create, {'package_set_id': package_set.id } 
end.to change(Order, :count).by(1) 
+0

工作的解决方案,我会批准,但不存在任何其他的解决方案,实际上是通过RSpec的手动重新加载它? – Laurent

+0

@Laurent也许你的例子很少,但为什么要测试一个控制器三次,然后检查它是否完成了三次?为什么不测试一次? –

+0

是的测试集缩短了,我已经在测试一个请求之前。我正在测试这种方式,因为在所有这些下面有一个胖订单分配逻辑,我需要确保它在连续添加物品时能够正确运行.. – Laurent

0

您可以在@order变量在before - 阻塞复位:

describe Class do 
    before(:each) do 
     @order = Order.new() 
    end 

    context "with multiple package sets from different shops" do 
     #... 
    end 
end 
+1

这并不理想,因为它会在测试中移动控制器逻辑,这可能会在以后出现问题,但这个想法就在这里。我想避免这样做,但我看到没有其他的事情要做...... – Laurent