Skip to content

Instantly share code, notes, and snippets.

@itarato
Last active April 5, 2024 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itarato/234eef6e01605a59a28695b312152809 to your computer and use it in GitHub Desktop.
Save itarato/234eef6e01605a59a28695b312152809 to your computer and use it in GitHub Desktop.
Tip on how to make a test mock builder for composite denormalized structures

Tip for test mock builders for denormalized attributes

(This is just one recommendation - and doesn't talk about error-free data structure design.)

Let's say there is a Project class that needs a convenience builder for testing. This Project consist of a company who owns the project and a list of tickets - where a ticket is just a name and the same company denormalized (for reasons). Since this company attribute is just a denormalization - it is/must-be consistent.

Don't do

When redundancy exists in data, do not prepare final objects too early. It will allow an inconsistent setup.

class ProjectBuilder
	def intialize(company_tag)
		@company = Company.new(company_tag)
		@tickets = []
	end

	def add_ticket(ticket)
		@tickets.push(ticket)
	end

	def build
		Project.new(
			company: @company,
			tickets: @tickets,
		)
	end
end

builder = ProjectBuilder.new(:ACME)
builder.add_ticket(Ticket.new("Paint a tunnel entrance", company: Company.new(:ROADRUNNER))) # Erroneus company.
builder.add_ticket(Ticket.new("TNT the cliff", company: Company.new(:WILEECOYOTE))) # Another erroneus company.
builder.build # Inconsistent company.

Do

Allow late building of attributes and consider re-normalizing (avoid redundant and diconnected attribute collection):

class ProjectBuilder
	def intialize(company_tag)
		@company = Company.new(company_tag)
		@ticket_names = []
	end

	def add_ticket(ticket_name) # No redundant attribute (company).
		@ticket_names.push(ticket)
	end

	def build
		Project.new(
			company: @company,
			tickets: @ticket_names.map { Ticket.new(_1, @company) }, # Late building.
		)
	end
end

builder = ProjectBuilder.new(:ACME)
builder.add_ticket("Paint a tunnel entrance")
builder.add_ticket("TNT the cliff")
builder.build # Consistent company.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment