Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/recruit-tech/dicon
DICONtainer Generator for go.
https://github.com/recruit-tech/dicon
Last synced: about 11 hours ago
JSON representation
DICONtainer Generator for go.
- Host: GitHub
- URL: https://github.com/recruit-tech/dicon
- Owner: recruit-tech
- License: apache-2.0
- Created: 2018-08-07T02:56:18.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2019-09-12T14:48:24.000Z (about 5 years ago)
- Last Synced: 2024-06-20T03:42:13.622Z (5 months ago)
- Language: Go
- Homepage:
- Size: 85 KB
- Stars: 11
- Watchers: 12
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# dicon
DICONtainer Generator for go.
[![CircleCI](https://circleci.com/gh/recruit-tech/dicon.svg?style=svg)](https://circleci.com/gh/recruit-tech/dicon)
[![Go Report Card](https://goreportcard.com/badge/github.com/recruit-tech/dicon)](https://goreportcard.com/report/github.com/recruit-tech/dicon)## Getting Started
### Prerequisites
- Go 1.9+
- make### Installing
```
$ go get -u github.com/recruit-tech/dicon/cmd/dicon
```### How to use
1. Write container interface and comment `+DICON` over it.```container.go
// +DICON
type Container interface {
UserService() (UserService, error)
UserRepository() (UserRepository, error)
}
```2. 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.```user.go
type User struct {
ID int64
Name string
}
``````userrepository.go
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
}
``````userservice.go
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
}
```3. generate!
```
$ dicon generate --pkg sample
```4. You can get the container implementation!
```dicon_gen.go
// 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
}
```5. Use it!
```.go
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)```go
// 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.
```go
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
- generate
```
$ dicon generate -h
NAME:
dicon generate - generate dicon_gen fileUSAGE:
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
```
- generate mock
```
$ dicon generate-mock -h
NAME:
dicon generate-mock - generate dicon_mock fileUSAGE:
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](LICENSE) file for details