buildergen

Usage

Step 1: Install this package

go install github.com/Jh123x/buildergen@latest

Install this package start using it

Step 2: Use the package

There are multiple ways to use this package

Step 2a: Using go generate

Write the go generate comment as shown in the example below.

package examples

import "github.com/Jh123x/buildergen/examples/nested"

//go:generate buildergen -src=./test.go -name Person

type Person struct {
	ID        int
	Name      string
	Email     *string // Optional field
	PhoneBook []*Contact
	MapVal    map[string]string `json:"map_val"`
	T         nested.Test
}

type Contact struct {
	Name  string
	Phone string
}

Step 2b: Using the command line

Another way to use BuilderGen using the command line.

buildergen -src=./examples/test.go -name Person

This will generate the same builder as the go:generate method.

Step 2c: Using the yaml config

Another way to use BuilderGen is to use a config file

buildergen --config ./path/to/config.yaml

The config file should look something like this

configs:
- source: ./internal/cmd/ttypes.go
  name: Config
- source: ./internal/cmd/ttypes_test.go
  name: testCase
  destination: ./internal/cmd/ttypes_builder_test.go
- source: ./examples/benchmark/benchmark.go
  name: Data
- source: ./examples/person.go
  name: Person

This use case is more suitable for those who wants to build a builder for structs in other libraries but want to store the mocks directly within the a mocks/test directory.

Step 3: Using the builder

After running the go generate, the generated file will look something like this.

// Code generated by BuilderGen
package examples

import (
	"github.com/Jh123x/buildergen/examples/nested"
)

type PersonBuilder struct {
	ID        int
	Name      string
	Email     *string
	PhoneBook []*Contact
	MapVal    map[string]string `json:"map_val"`
	T         nested.Test
}

func NewPersonBuilder(b *Person) *PersonBuilder {
	return &PersonBuilder{
		ID:        b.ID,
		Name:      b.Name,
		Email:     b.Email,
		PhoneBook: b.PhoneBook,
		MapVal:    b.MapVal,
		T:         b.T,
	}
}

func (b *PersonBuilder) WithID(id int) *PersonBuilder {
	b.ID = id
	return b
}

func (b *PersonBuilder) WithName(name string) *PersonBuilder {
	b.Name = name
	return b
}

func (b *PersonBuilder) WithEmail(email *string) *PersonBuilder {
	b.Email = email
	return b
}

func (b *PersonBuilder) WithPhoneBook(phonebook []*Contact) *PersonBuilder {
	b.PhoneBook = phonebook
	return b
}

func (b *PersonBuilder) WithMapVal(mapval map[string]string) *PersonBuilder {
	b.MapVal = mapval
	return b
}

func (b *PersonBuilder) WithT(t nested.Test) *PersonBuilder {
	b.T = t
	return b
}

func (b *PersonBuilder) Build() *Person {
	return &Person{
		ID:        b.ID,
		Name:      b.Name,
		Email:     b.Email,
		PhoneBook: b.PhoneBook,
		MapVal:    b.MapVal,
		T:         b.T,
	}
}

Step 4: Use the builder

Use the builder wherever you need it.


var defaultPerson = &Person{
	ID: 1,
	Name: "John",
	Email: nil,
}

...
func TestXXX(t *testing.T){
	clonedPerson := NewPersonBuilder(defaultPerson).WithID(12).WithName("Johnny").Build() // ID and Name changes
	...
	// Use clonedPerson
}