如何使用RSpec测试组合对象属性的设置?

时间:2012-02-19 15:39:25

标签: ruby oop

比如说我在我的Rails应用程序中有两个类 - Customer类和Card类。 Customer类由Card类组成,即客户有卡。

然后我有一个定义了'do_something'动作的Rails控制器,它将使用在POST上传入的参数初始化一个新的Customer实例(反过来将在内部创建一个新的Card实例)。 p>

然后将卡的编号设置如下:

class ShopController < ApplicationController
    def do_something
        customer = Customer.new params
        customer.card.number = params[:card_number]
        ...
    end
end

如何在RSpec测试中测试卡号的分配?理想情况下,如果'should_receive_chain'存在,我们可以写:

describe MyController do
    describe "POST 'do_something'" do
        it "should set card number"
            params = { :card_number => '1234' }
            card_mock.should_receive_chain(:card, :number).with '1234'
            post :do_something
        end
    end
end

有什么想法吗?也许它无法轻易测试的事实是代码味道,也许我应该在Customer类上创建一个setter方法?

2 个答案:

答案 0 :(得分:0)

我认为你在错误的水平测试这个。如果您愿意在单独的声明中设置卡号,那么最好创建一个函数来帮助解决这个问题。

class Customer
  def self.new_with_card_number(params, number)
    customer = new(params)
    customer.card.number = number
    customer
  end
end

describe Customer do
  it 'creates a card with a number' do
    customer = described_class.new_with_card_number({}, '1234')
    customer.card.number.should == '1234'
  end
end

然后您可以将控制器更改为:

class ShopController < ApplicationController
  def do_something
    customer = Customer.new_with_card_number(params, params[:card_number])
  end
end

更简单的解决方案可能是简单地在表单中命名参数,以便自动设置卡号:

params[:customer][:card_attributes][:card_number]

然后,您可以将呼叫更改为customer = Customer.new(params)

答案 1 :(得分:0)

我会更改Customer模型以添加accepted_nested_attributes_for :card并将控制器操作更改为

class ShopController < ApplicationController
  def do_something
    customer = Customer.create params[:customer]
    ...
  end
end

然后您的规范可能看起来像

describe ShopController do
  describe 'POST /do_something' do
    it "sets the card's card number" do
      post :do_something, :customer => 
                              {
                                :card_attributes => {:card_number => '1234'}
                              }
      Customer.last.card.number.should == '1234'
    end
  end
end