Я столкнулся с путаницей, соединяя тестовый двойник и обрезая его. Мой вопрос: какой самый подходящий способ проверить методы confirm_purchase_order
и create_order
в class PurchaseOrder
?Прерывание возвращаемого значения в RSpec - правильное использование удвоений и заглушек
Я включил соответствующий код следующий код:
class PurchaseOrder
attr_reader :customer, :products
def initialize(customer)
@products = {}
@customer = customer
end
....some other methods
def add_product(product, quantity = 1)
@products[product] = (@products[product] ? @products[product] + quantity : quantity)
puts "You haved added #{quantity} #{product.title}'s to your purchase order"
end
def confirm_purchase_order
purchase_order_total
raise "Your PO appears to be empty! Add some products and try again." unless self.total.to_f.round(2) > 0
create_order
create_invoice
return "We have generated an Invoice and created an order."
end
def create_order
order = Order.new(customer)
order.products = @products.clone
end
def create_invoice
invoice = Invoice.new(customer)
invoice.products = @products.clone
end
end
class Order
attr_reader :customer
attr_accessor :status, :total, :products
def initialize(customer)
@products = {}
@status = :pending
@customer = customer
end
class Customer
attr_reader :name, :type
def initialize(name, type)
@name = name.to_s
@type = type.to_sym
end
class Invoice
attr_reader :customer, :products
attr_accessor :total
def initialize(customer, products)
@products = {}
@customer = customer
@payment_recieved = false
end
end
Я хочу протестировать метод confirm_purchase_order
, а также метод create_order
в class PurchaseOrder
. Мой подход до сих пор:
Мне нужно несколько объектов двойников и фактической PurchaseOrder object
describe PurchaseOrder do
let(:product) { double :product, title: "guitar", price: 5 }
let(:order) { instance_double(Order) }
let(:customer) { double :customer, name: "Bob", type: :company }
let(:products) { {:product => 1} }
let(:purchase_order) { PurchaseOrder.new(customer) }
describe "#create_order" do
it "returns an order" do
expect(Order).to receive(:new).with(customer).and_return(order)
allow(order).to receive(products).and_return(???products??!)
purchase_order.add_product(product, 1)
purchase_order.create_order
expect(order.products).to eq (products)
end
end
end
Я также посмотрел на использование:
# order.stub(:products).and_return(products_hash)
# allow_any_instance_of(Order).to receive(:products) { products_hash }
# order.should_receive(:products).and_return(products_hash)
Для установки порядка дважды для возврата продукции хеш, когда вызывается order.products
, но все они чувствуют, что они слишком «фальсифицируют» тест. Каков наиболее подходящий способ тестирования методов confirm_purchase_order
и create_order
в class PurchaseOrder
?
Спасибо Йесперу за такой всеобъемлющий ответ. Я работаю над рефакторингом.Я не сталкивался с этим «шаблоном проектирования» (я думаю, вы могли бы его назвать), чтобы гарантировать, что вы делегируете ответственность за создание объекта для этого класса с помощью метода класса таким образом, но полностью понимаете, почему это необходимо с точки зрения инкапсуляции , –