我正在努力实施封装(但可能做得不好),并想在Rspec中测试代码。当在工厂类中实例化Customer类时,它将采用一个Object类(作为容器)。通过尚不存在的UI,客户将创建一个订单。

我当前的测试如下。我只想确认订单是Order类。

describe 'Customer' do
  let(:customer){Customer.new}
  let(:customer_with_instantiation){Customer.new(:klass=>order, :name=>'Oscar Wilde', :number=>'0234567')}

  let(:order){double :order, :name=>:order}

  it 'klass object to be the order class when customer is instantiated with a klass attribute' do
    expect(customer_with_instantiation.klass).to be_a(order)
  end

end


类代码如下:

    class Customer

      attr_accessor :name, :number, :klass

      DEFAULT_CUSTOMER_ORDER = {:order_detail => [{ :dish=>"",
                                                    :item_count=>0 }],
                                :order_total_cost=>0 }

      def initialize(options={})
        @name=options.fetch(:name, "")
        @number=options.fetch(:number, "")
        @klass=options.fetch(:klass, Object)
        @customer_order=DEFAULT_CUSTOMER_ORDER
      end

      def place_order(menu)
        #requires user input
        customer_order=klass.new({:order_detail => [{:dish => :pizza, :item_count => 3},
                                                    {:dish => :burger, :item_count => 3}],
                                  :order_total_cost => 210})
        klass.test_customer_order(customer_order, self)
      end

    end



  class Order

     attr_reader :order_detail, :order_total_cost
     attr_accessor :total_check



 def initialize(options={})
    @order_detail=options.fetch(:order_detail, Object)
    @order_total_cost=options.fetch(:order_total_cost, Object)
  end

  def self.test_customer_order(customer_order, customer, menu, assistant)
    customer_order.total_check = 0
    customer_order.order_detail.each do |order_item|
      menu.dishes.each do |dish|
        if order_item[:dish]==dish.name
          customer_order.total_check += dish.price*order_item[:item_count]
        end
      end
    end
    assistant.take_order(customer_order, customer, customer_order.total_check)
  end

end


任何帮助表示感谢!

最佳答案

通过使用be_a,您正在测试klassklass的实例,可能不是您想要的。

在我看来,当测试initialize方法和klass的吸气剂(实际上是在做什么)时,您应该只对确认发送到Customer.new的内容能够被读取感兴趣。然后。

所以也许是这样的:

class Foo
  attr_reader :klass
  def initialize(args)
    @klass = args.fetch(:klass)
  end
end

describe Foo do
  describe "#initialize" do
    let(:klass) { double }
    let(:instance) { Foo.new(klass: klass)}
    it "sets klass" do
      expect(instance.klass).to eq(klass)
    end
  end
end


一些一般要点:


如果要测试订单是否为klass的实例,则可能应该重写代码以使其更易于测试
在这种情况下,klass不是一个非常有用的名称。目前尚不清楚为什么Customer需要一个杯子。
您想使订单与客户脱钩,但是客户显然正在对订单界面进行一些假设。你真的有成就吗?
我建议不要将测试方法放在类本身中,而应该放在测试文件中。
Object中使用fetch作为默认值可能不是您想要的。首先,您可能希望它们是某个类的实例,而不是类对象。
Customer类的实例创建订单真的是工作吗?如果要确保可以根据用户输入实例化任何种类的抽象顺序,那么也许单独的OrderCreator类更合适?此类可以接受用户数据和订单类别以及受影响的客户。

关于ruby - 如何在Rspec中 stub Class对象?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28538811/

10-12 15:59