Альтернативный подход к написанию приложения немного по-другому.
Извлеките всю важную логику, которую вы хотите протестировать, в классы ruby без зависимостей от базы данных.
Пишите тесты только для этих классов — ваши тесты будут работать! :)
Например
ProductQuantity = Struct.new(:product_id, :quantity)
class Customer < ActiveRecord
def create_order(product_quantities)
product_ids = product_quantities.map(&:product_id)
products = Product.where(:id => product_ids).pluck(:id, unit_price).to_h
total = product_quantities.reduce(0) do |sum, p|
sum += p.quantity * products.fetch(p.product_id, 0)
end
Order.create!(:customer_id => id, :total => total)
end
end
Извлечение бизнес-логики из зависимостей базы данных
class Customer < ActiveRecord
def create_order(product_quantities)
products = Product.where(:id => product_ids).pluck(:id, unit_price).to_h
total = CalculateNewOrderTotal.from(products, product_quantities)
Order.create!(:customer_id => id, :total => total)
end
end
module CalculateNewOrderTotal
def self.from(products, product_quantities)
product_quantities.reduce(0) do |sum, p|
sum += p.quantity * products.fetch(p.product_id, 0)
end
end
end
Теперь модуль CalculateNewOrderTotal
может быть полностью покрыт очень быстрыми тестами, которые не требуют макетов или фактической базы данных.
Вы по-прежнему можете писать тесты счастливого пути с реальной базой данных для метода Customer.create_order
.
Дополнительные преимущества
Ваша бизнес-логика не зависит от структуры постоянства.
Ваша бизнес-логика не зависит от схемы сохранения. Вы можете изменить способ хранения данных, не затрагивая важный код бизнес-логики.
Никаких имитаций
Никаких дополнительных слоев. абстракций — вы по-прежнему можете использовать все преимущества ActiveRecord, например, обернуть вызов метода транзакцией.
Никакие другие фреймворки или гемы не задействованы — чистый ruby и RSpec или тестовый фреймворк по вашему выбору :)
person
Fabio
schedule
28.10.2020