我正在創建一個將CSV文件導入到多個表的導入功能。我創建了一個名爲CsvParser
的模塊,它解析CSV文件並創建記錄。接收創建操作的模型擴展了CsvParser
。他們打電話給CsvParser.create
,並傳遞正確的屬性順序和一個可選的lambda,稱爲value_parser
。這個lambda將hash中的值轉換爲優先格式。測試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
方法裏面的原因是因爲拉姆達就像是屬於這種模式業務規則。
我的問題是我應該如何測試這個lambda。我應該在模型還是CsvParser中測試它?我應該測試lambda本身還是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 ::。我只是想知道如何測試像這樣的東西,當它是一個方法中的變量時。 –
2012-04-12 10:15:23
如果lambda不能被重構出來,我會以任何其他方法來測試它。如果它是一個非常複雜的lambda,依靠大量的局部變量,那麼這可能表明它想成爲它自己的實例。作爲一般規則,難以測試的方法需要重構! – user208769 2012-04-13 17:29:56
今天我意識到有一種叫做方法對象的東西。它可以像lambda一樣使用,唯一的區別是我可以使用方法的代碼而不是lambda。我認爲它比定義一個lambda作爲一個常量更清潔。所以,而不是傳遞lambda作爲參數我現在使用方法(:) –
2012-04-16 12:10:59