dicon

package module
v0.0.0-...-fd252ed Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2018 License: Apache-2.0 Imports: 12 Imported by: 0

README

dicon

DICONtainer Generator for go.

CircleCI Go Report Card

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.
// +DICON
type Container interface {
	UserService() (UserService, error)
	UserRepository() (UserRepository, error)
}
  1. 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
}
  1. generate!
$ dicon generate --pkg sample
  1. 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
}
  1. 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

  • generate
$ 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
  • generate mock
$ 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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DetectCyclicDependency

func DetectCyclicDependency(funcs []FuncType) error

Types

type ContainerGenerator

type ContainerGenerator struct {
	Generator
}

func NewContainerGenerator

func NewContainerGenerator() *ContainerGenerator

func (*ContainerGenerator) AppendMethod

func (g *ContainerGenerator) AppendMethod(funcs []FuncType, _ string)

func (*ContainerGenerator) AppendStructDefs

func (g *ContainerGenerator) AppendStructDefs(it *InterfaceType)

func (*ContainerGenerator) Generate

func (g *ContainerGenerator) Generate(it *InterfaceType, fs []FuncType) error

func (*ContainerGenerator) RelativePackageName

func (g *ContainerGenerator) RelativePackageName(packageName string) string

type CyclicDependencyError

type CyclicDependencyError struct {
	// contains filtered or unexported fields
}

func (*CyclicDependencyError) Error

func (e *CyclicDependencyError) Error() string

type FuncType

type FuncType struct {
	ArgumentTypes []ParameterType
	ReturnTypes   []ParameterType
	PackageName   string
	Comments      []string
	Name          string
}

func FindConstructors

func FindConstructors(packageName string, filenames []string, funcnames []string) ([]FuncType, error)

type Generator

type Generator struct {
	PackageName string
	// contains filtered or unexported fields
}

func (*Generator) AppendHeader

func (g *Generator) AppendHeader(it *InterfaceType)

func (*Generator) Out

func (g *Generator) Out(w io.Writer, filename string) error

func (*Generator) Printf

func (g *Generator) Printf(format string, args ...interface{})

type InterfaceType

type InterfaceType struct {
	PackageName    string
	Comments       []string
	Name           string
	Funcs          []FuncType
	DependPackages []Package
}

func FindDependencyInterfaces

func FindDependencyInterfaces(packageName string, filenames []string, targetNames []string) ([]InterfaceType, error)

func FindDicon

func FindDicon(packageName string, filenames []string) (*InterfaceType, error)

func (*InterfaceType) AggregateFuncName

func (i *InterfaceType) AggregateFuncName() []string

type MockGenerator

type MockGenerator struct {
	Generator
}

func NewMockGenerator

func NewMockGenerator() *MockGenerator

func (*MockGenerator) AppendImports

func (g *MockGenerator) AppendImports(targets []InterfaceType)

func (*MockGenerator) AppendMockStruct

func (g *MockGenerator) AppendMockStruct(it *InterfaceType)

func (*MockGenerator) Generate

func (g *MockGenerator) Generate(it *InterfaceType, targets []InterfaceType) error

type Outer

type Outer interface {
	Out(w io.Writer, filename string) error
}

type Package

type Package struct {
	Name string
	Path string
}

type ParameterType

type ParameterType struct {
	DeclaredPackageName string
	// contains filtered or unexported fields
}

func NewParameterType

func NewParameterType(packageName string, expr ast.Expr) *ParameterType

func (*ParameterType) ConvertName

func (p *ParameterType) ConvertName(packageName string) string

func (*ParameterType) SimpleName

func (p *ParameterType) SimpleName() string

Directories

Path Synopsis
cmd
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL