dicon
[DEPRECATED] this repository has been moved to: https://github.com/recruit-tech/dicon
DICONtainer Generator for go.
Getting Started
Prerequisites
Installing
$ go get -u github.com/akito0107/dicon
How to use
- Write container interface and comment
+DICON
over it.
// +DICON
type Container interface {
UserService() (UserService, error)
UserRepository() (UserRepository, error)
}
- Prepare dependencies. You must write constructor which meets below requirements:
- method name must be
New
+ Interface name
- return type must be (Interface, error) tuple.
- dependencies which use this instance must be passed via the constructor.
type User struct {
ID int64
Name string
}
type UserRepository interface {
FindByID(id int64) (*User, error)
}
type userRepository struct{}
func (*userRepository) FindByID(id int64) (*User, error) {
// STUB
return &User{ID: id, Name: "foo"}, nil
}
func NewUserRepository() (UserRepository, error) {
return &userRepository{}, nil
}
type UserService interface {
Find(id int64) (*User, error)
}
type userService struct {
repo UserRepository
}
func (us *userService) Find(id int64) (*User, error) {
return us.repo.FindByID(id)
}
func NewUserService(repo UserRepository) (UserService, error) {
return &userService{
repo: repo,
}, nil
}
- generate!
$ dicon generate --pkg sample
- You can get the container implementation!
// Code generated by "dicon"; DO NOT EDIT.
package sample
import (
"fmt"
"github.com/pkg/errors"
)
type dicontainer struct {
store map[string]interface{}
}
func NewDIContainer() Container {
return &dicontainer{
store: map[string]interface{}{},
}
}
func (d *dicontainer) UserRepository() (UserRepository, error) {
if i, ok := d.store["UserRepository"]; ok {
instance, ok := i.(UserRepository)
if !ok {
return nil, fmt.Errorf("invalid instance is cached %v", instance)
}
return instance, nil
}
instance, err := NewUserRepository()
if err != nil {
return nil, errors.Wrap(err, "creation UserRepository failed at DICON")
}
d.store["UserRepository"] = instance
return instance, nil
}
func (d *dicontainer) UserService() (UserService, error) {
if i, ok := d.store["UserService"]; ok {
instance, ok := i.(UserService)
if !ok {
return nil, fmt.Errorf("invalid instance is cached %v", instance)
}
return instance, nil
}
dep0, err := d.UserRepository()
if err != nil {
return nil, errors.Wrap(err, "resolve UserRepository failed at DICON")
}
instance, err := NewUserService(dep0)
if err != nil {
return nil, errors.Wrap(err, "creation UserService failed at DICON")
}
d.store["UserService"] = instance
return instance, nil
}
- Use it!
di := NewDIContainer()
u, err := di.UserService()
....
Generate Mock
dicon's target interfaces are often mocked in unit tests.
So, dicon also provides a tool for automated mock creation.
You just type
$ dicon generate-mock --pkg sample
then, you get mocks (by the default, under the mock
package)
// Code generated by "dicon"; DO NOT EDIT.
package mock
type UserRepositoryMock struct {
FindByIdMock func(a0 int64) (*entity.User, error)
}
func NewUserRepositoryMock() *UserRepositoryMock {
return &UserRepositoryMock{}
}
func (mk *UserRepositoryMock) FindById(a0 int64) (*entity.User, error) {
return mk.FindByIdMock(a0)
}
type UserServiceMock struct {
FindMock func(a1 int64) (*entity.User, error)
}
func NewUserServiceMock() *UserServiceMock {
return &UserServiceMock{}
}
func (mk *UserServiceMock) Find(a0 int64) (*entity.User, error) {
return mk.FindMock(a0)
}
Generated mocks have XXXMock
func as a field (XXX is same as interface method name).
In testing, you can freely rewrite behaviors by assigning func
to this field.
func TestUserService_Find(t *testing.T) {
m := mock.NewUserRepositoryMock()
m.FindByIdMock = func(id int64) (*entity.User, error) {
// mocking logic....
return user, nil
}
service := NewUserService(m) // passing the mock
if _, err := service.Find(id); err != nil {
t.Error(err)
}
}
Options
$ dicon generate -h
NAME:
dicon generate - generate dicon_gen file
USAGE:
dicon generate [command options] [arguments...]
OPTIONS:
--pkg value, -p value target package(s).
--out value, -o value output file name (default: "dicon_gen")
--dry-run
$ dicon generate-mock -h
NAME:
dicon generate-mock - generate dicon_mock file
USAGE:
dicon generate-mock [command options] [arguments...]
OPTIONS:
--pkg value, -p value target package(s).
--out value, -o value output file name (default: "dicon_mock")
--dist value, -d value output package name (default: "mock")
--dry-run
License
This project is licensed under the Apache License 2.0 License - see the LICENSE file for details