go install github.com/Jh123x/buildergen@latest
Install this package start using it
There are multiple ways to use this package
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
}
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.
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
mode: DEFAULT # Default mode uses golang built in AST
- source: ./examples/person.go
name: Person
mode: FAST # Fast mode uses custom parsers but may have more error edge cases. Use this when generation speed is important.
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.
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,
}
}
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
}