My last post was about a class for building test data objects in C#. This post describes the same tool, but implemented in Ruby. The C# version was written first but I originally came up with the solution in my head using Ruby, and then I translated it to C#. The Ruby version was easier to write and is easier to use thanks to Ruby’s dynamic nature making generics unnecessary. Here are my example domain classes: class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
class Property
attr_accessor :street, :manager
def initialize(street, manager)
@street = street
@manager = manager
end
end
and the test class showing what the builder does:
class Test_Builder < Test::Unit::TestCase
def setup
@build = Builder.new
@build.configure({
Property => lambda { Property.new '127 Creek St', @build.a(Person) },
Person => lambda { Person.new 'Liam', 26 }
})
end
def test_create
assert_not_nil @build
end
def test_can_get_a_person
@person = @build.a(Person)
assert_not_nil @person
assert_equal 'Liam', @person.name
assert_equal 26, @person.age
end
def test_can_get_a_modified_person
@person = @build.a Person do |person|
person.age = 999
end
assert_not_nil @person
assert_equal 'Liam', @person.name
assert_equal 999, @person.age
end
def test_can_get_a_different_type_that_depends_on_a_type_that_has_not_been_configured_yet
@my_place = @build.a(Property)
assert_not_nil @my_place
assert_equal '127 Creek St', @my_place.street
assert_equal @build.a(Person).name, @my_place.manager.name
end
end
Finally, the implementation of Builder:
class Builder
# defaults is a hash of Class => creation lambda
def configure defaults
@defaults = defaults
end
def a(klass)
temp = @defaults[klass].call()
yield temp if block_given?
temp
end
end