使用Mocha测试关联方法

时间:2010-11-15 18:55:28

标签: ruby-on-rails associations mocha

我有一个带有Order和Refund模型的Rails应用程序。订单has_many:退款。一切都很好。我正在尝试在控制器中编写退款逻辑的功能测试。这就是我现在所拥有的:

test "should not process partial paypal refund for partially refunded order when refund total plus refund amount is greater than order total" do
    set_super_admin_login_credentials
    o = Order.new
    o.stubs({:id => 1234567, :source => "PayPal", :total => 39.95, :user => users(:dave)})
    Order.stubs(:find).with(1234567).returns(o)
    get :refund, {:order_id => 1234567}
    assert_equal o, assigns(:order)
    o.refunds.build.stubs({:amount => 1.0})
    o.refunds.build.stubs({:amount => 30.00})
    assert_raise do
        post :refund, {:order_id => 1234567, :refund_amount => 10.00}
    end
end

在控制器中,退款方法如下所示:

def refund    
    @order = Order.find(params[:order_id])
    return if request.get?

    amount = params[:refund_amount].to_f
    raise "Cannot refund order for more than total" if (@order.refunds.sum(&:amount) + amount)
    # Do refund stuff
end

一些注意事项:

  1. 我基于Ryan Bates' Railscast. o.refunds.build位如果这不正确或不再相关,那就是有用的信息。

  2. 我见过很多关于如何实际执行sum方法的信息,有些信息是&而有些信息没有。在script/console中,&爆炸但没有它,我得到一个实际的总和。但是,在我的控制器中,如果我从&:amount切换到:amount,我会收到以下消息:NoMethodError: undefined method +'for:amount:Symbol`

  3. 我觉得某些概念信息缺失而不是某处的错误,所以我会感激一些指示。

1 个答案:

答案 0 :(得分:1)

终于弄明白了这个问题。我将一个空关联存根为[],而不是让它nil让Rails处理其他一些方法。所以,当我改变一个时,另一个会失败。明智的话:Enumerable#sumActiveRecord::Associations::AssociationCollection#sum采用完全不同的参数。 :)

因此,通过更改存根以在:refunds => []中取消sumusing a string for the field name,我恢复了正常状态。所以,这是上述代码的功能版本:

test "should not process partial paypal refund for partially refunded order when refund total plus refund amount is greater than order total" do
    set_super_admin_login_credentials
    o = Order.new
    o.stubs({:id => 1234567, :source => "PayPal", :total => 39.95, :user => users(:dave)})
    Order.stubs(:find).with(1234567).returns(o)
    get :refund, {:order_id => 1234567}
    assert_equal o, assigns(:order)
    o.refunds.build.stubs({:amount => 1.0})
    o.refunds.build.stubs({:amount => 30.00})
    assert_raise do
        post :refund, {:order_id => 1234567, :refund_amount => 10.00}
    end
end

def refund    
    @order = Order.find(params[:order_id])
    return if request.get?

    amount = params[:refund_amount].to_f
    raise "Cannot refund order for more than total" if (@order.refunds.sum('amount') + amount)
    # Do refund stuff
end