Я создаю функцию импорта, которая импортирует CSV-файлы в несколько таблиц. Я создал модуль под названием CsvParser
, который анализирует CSV-файл и создает записи. Мои модели, которые получают действия create, расширяют CsvParser
. Они делают звонок до CsvParser.create
и передают правильный порядок атрибутов и необязательную лямбда под названием value_parser
. Эта лямбда преобразует значения в хэш в предпочтительный формат.Тестирование lambda
class Mutation < ActiveRecord::Base
extend CsvParser
def self.import_csv(csv_file)
attribute_order = %w[reg_nr receipt_date reference_number book_date is_credit sum balance description]
value_parser = lambda do |h|
h["is_credit"] = ((h["is_credit"] == 'B') if h["is_credit"].present?)
h["sum"] = -1 * h["sum"].to_f unless h["is_credit"]
return [h]
end
CsvParser.create(csv_file, self, attribute_order, value_parser)
end
end
Причина, по которой я использую лямбда вместо чеков внутри метода CsvParser.create
потому, что лямбда, как бизнес-правило, принадлежит к этой модели.
Мой вопрос: как я должен проверить эту лямбду. Должен ли я тестировать его в модели или CsvParser? Должен ли я проверить сам лямбда или результат массива метода self.import
? Может быть, я должен создать еще одну структуру кода?
Мой CsvParser выглядит следующим образом:
require "csv"
module CsvParser
def self.create(csv_file, klass, attribute_order, value_parser = nil)
parsed_csv = CSV.parse(csv_file, col_sep: "|")
records = []
ActiveRecord::Base.transaction do
parsed_csv.each do |row|
record = Hash.new {|h, k| h[k] = []}
row.each_with_index do |value, index|
record[attribute_order[index]] = value
end
if value_parser.blank?
records << klass.create(record)
else
value_parser.call(record).each do |parsed_record|
records << klass.create(parsed_record)
end
end
end
end
return records
end
end
Я проверяю сам модуль: требуется 'spec_helper'
describe CsvParser do
it "should create relations" do
file = File.new(Rails.root.join('spec/fixtures/files/importrelaties.txt'))
Relation.should_receive(:create).at_least(:once)
Relation.import_csv(file).should be_kind_of Array
end
it "should create mutations" do
file = File.new(Rails.root.join('spec/fixtures/files/importmutaties.txt'))
Mutation.should_receive(:create).at_least(:once)
Mutation.import_csv(file).should be_kind_of Array
end
it "should create strategies" do
file = File.new(Rails.root.join('spec/fixtures/files/importplan.txt'))
Strategy.should_receive(:create).at_least(:once)
Strategy.import_csv(file).should be_kind_of Array
end
it "should create reservations" do
file = File.new(Rails.root.join('spec/fixtures/files/importreservering.txt'))
Reservation.should_receive(:create).at_least(:once)
Reservation.import_csv(file).should be_kind_of Array
end
end
Спасибо за обстоятельный, четкий ответ. Я последовал вашим советам и смог проверить константу, потому что я мог назвать Class :: <имя константы>. Мне просто интересно, как я должен тестировать что-то подобное, когда это будет переменная в методе. –
Если лямбда не может быть реорганизована, я бы проверил ее как любой другой метод. Если это очень сложная лямбда, опираясь на множество локальных переменных, это может указывать на то, что она хочет быть ее собственным экземпляром. Как правило, методы, которые трудно тестировать, нуждаются в рефакторе! – user208769
Сегодня я понял, что есть что-то, называемое объектом метода. Его можно использовать так же, как лямбда, с той лишь разницей, что я могу использовать код метода вместо лямбда.Я думаю, что это более чище, чем определение лямбда как константы. Поэтому вместо передачи лямбда в качестве параметра я теперь использую метод (:) –