Testing EvaluatorClassDefiner Attribute Handling in Factory Bot
This test suite validates the EvaluatorClassDefiner component in Factory Bot, which handles attribute evaluation and inheritance in test factories. The specs ensure proper attribute handling, block evaluation, and parent-child relationships for factory evaluators.
Test Coverage Overview
Implementation Analysis
Technical Details
Best Practices Demonstrated
thoughtbot/factory_bot
spec/factory_bot/evaluator_class_definer_spec.rb
describe FactoryBot::EvaluatorClassDefiner do
it "returns an evaluator when accessing the evaluator class" do
evaluator = define_evaluator(parent_class: FactoryBot::Evaluator)
expect(evaluator).to be_a(FactoryBot::Evaluator)
end
it "adds each attribute to the evaluator" do
attribute = stub_attribute(:attribute) { 1 }
evaluator = define_evaluator(attributes: [attribute])
expect(evaluator.attribute).to eq 1
end
it "evaluates the block in the context of the evaluator" do
dependency_attribute = stub_attribute(:dependency) { 1 }
attribute = stub_attribute(:attribute) { dependency + 1 }
evaluator = define_evaluator(attributes: [dependency_attribute, attribute])
expect(evaluator.attribute).to eq 2
end
it "only instance_execs the block once even when returning nil" do
count = 0
attribute = stub_attribute(:attribute) {
count += 1
nil
}
evaluator = define_evaluator(attributes: [attribute])
2.times { evaluator.attribute }
expect(count).to eq 1
end
it "sets attributes on the evaluator class" do
attributes = [stub_attribute, stub_attribute]
evaluator = define_evaluator(attributes: attributes)
expect(evaluator.attribute_lists).to eq [attributes]
end
context "with a custom evaluator as a parent class" do
it "bases its attribute lists on itself and its parent evaluator" do
parent_attributes = [stub_attribute, stub_attribute]
parent_evaluator_class = define_evaluator_class(attributes: parent_attributes)
child_attributes = [stub_attribute, stub_attribute]
child_evaluator = define_evaluator(
attributes: child_attributes,
parent_class: parent_evaluator_class
)
expect(child_evaluator.attribute_lists).to eq [parent_attributes, child_attributes]
end
end
def define_evaluator(arguments = {})
evaluator_class = define_evaluator_class(arguments)
evaluator_class.new(FactoryBot::Strategy::Null)
end
def define_evaluator_class(arguments = {})
evaluator_class_definer = FactoryBot::EvaluatorClassDefiner.new(
arguments[:attributes] || [],
arguments[:parent_class] || FactoryBot::Evaluator
)
evaluator_class_definer.evaluator_class
end
def stub_attribute(name = :attribute, &value)
value ||= -> {}
double(name.to_s, name: name.to_sym, to_proc: value)
end
end