Skip to content

Commit

Permalink
feat: generate exported mocks with -e flag
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan-Feofanov authored Jan 31, 2023
1 parent 765cb0e commit a041b16
Show file tree
Hide file tree
Showing 19 changed files with 13,007 additions and 12 deletions.
23 changes: 17 additions & 6 deletions mocktail.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"go/format"
"go/importer"
Expand All @@ -18,8 +19,9 @@ import (
)

const (
srcMockFile = "mock_test.go"
outputMockFile = "mock_gen_test.go"
srcMockFile = "mock_test.go"
outputMockFile = "mock_gen_test.go"
outputExportedMockFile = "mock_gen.go"
)

const contextType = "context.Context"
Expand All @@ -45,6 +47,10 @@ func main() {
log.Fatal("get module path", err)
}

var exported bool
flag.BoolVar(&exported, "e", false, "generate exported mocks")
flag.Parse()

root := info.Dir

err = os.Chdir(root)
Expand All @@ -61,7 +67,7 @@ func main() {
return
}

err = generate(model)
err = generate(model, exported)
if err != nil {
log.Fatalf("generate: %v", err)
}
Expand Down Expand Up @@ -233,7 +239,7 @@ func getTypeImports(t types.Type) []string {
}
}

func generate(model map[string]PackageDesc) error {
func generate(model map[string]PackageDesc, exported bool) error {
for fp, pkgDesc := range model {
buffer := bytes.NewBufferString("")

Expand All @@ -243,7 +249,7 @@ func generate(model map[string]PackageDesc) error {
}

for _, interfaceDesc := range pkgDesc.Interfaces {
err = writeMockBase(buffer, interfaceDesc.Name)
err = writeMockBase(buffer, interfaceDesc.Name, exported)
if err != nil {
return err
}
Expand Down Expand Up @@ -279,7 +285,12 @@ func generate(model map[string]PackageDesc) error {
return fmt.Errorf("source: %w", err)
}

out := filepath.Join(filepath.Dir(fp), outputMockFile)
fileName := outputMockFile
if exported {
fileName = outputExportedMockFile
}

out := filepath.Join(filepath.Dir(fp), fileName)

log.Println(out)

Expand Down
63 changes: 61 additions & 2 deletions mocktail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
"github.com/stretchr/testify/require"
)

const testRoot = "./testdata/src"

func TestMocktail(t *testing.T) {
const testRoot = "./testdata/src"

if runtime.GOOS == "windows" {
t.Skip(runtime.GOOS)
}
Expand Down Expand Up @@ -70,3 +70,62 @@ func TestMocktail(t *testing.T) {
require.NoError(t, err)
}
}

func TestMocktail_exported(t *testing.T) {
const testRoot = "./testdata/exported"

if runtime.GOOS == "windows" {
t.Skip(runtime.GOOS)
}

dir, errR := os.ReadDir(testRoot)
require.NoError(t, errR)

for _, entry := range dir {
if !entry.IsDir() {
continue
}

t.Setenv("MOCKTAIL_TEST_PATH", filepath.Join(testRoot, entry.Name()))

output, err := exec.Command("go", "run", ".", "-e").CombinedOutput()
t.Log(string(output))

require.NoError(t, err)
}

errW := filepath.WalkDir(testRoot, func(path string, d fs.DirEntry, errW error) error {
if errW != nil {
return errW
}

if d.IsDir() || d.Name() != outputMockFile {
return nil
}

genBytes, err := os.ReadFile(path)
require.NoError(t, err)

goldenBytes, err := os.ReadFile(path + ".golden")
require.NoError(t, err)

assert.Equal(t, string(goldenBytes), string(genBytes))

return nil
})
require.NoError(t, errW)

for _, entry := range dir {
if !entry.IsDir() {
continue
}

cmd := exec.Command("go", "test", "-v", "./...")
cmd.Dir = filepath.Join(testRoot, entry.Name())

output, err := cmd.CombinedOutput()
t.Log(string(output))

require.NoError(t, err)
}
}
10 changes: 10 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ func TestMock(t *testing.T) {
}
```

## Exportable Mocks

If you need to use your mocks in external packages just add flag `-e`:

```shell
mocktail -e
```

In this case, mock will be created in the same package but in the file `mock_gen.go`.

<!--
Replacement pattern:
Expand Down
13 changes: 9 additions & 4 deletions syrup.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ package {{ .Name }}
// {{ .InterfaceName | ToGoCamel }}Mock mock of {{ .InterfaceName }}.
type {{ .InterfaceName | ToGoCamel }}Mock struct { mock.Mock }
// new{{ .InterfaceName | ToGoPascal }}Mock creates a new {{ .InterfaceName | ToGoCamel }}Mock.
func new{{ .InterfaceName | ToGoPascal }}Mock(tb testing.TB) *{{ .InterfaceName | ToGoCamel }}Mock {
// {{.ConstructorPrefix}}{{ .InterfaceName | ToGoPascal }}Mock creates a new {{ .InterfaceName | ToGoCamel }}Mock.
func {{.ConstructorPrefix}}{{ .InterfaceName | ToGoPascal }}Mock(tb testing.TB) *{{ .InterfaceName | ToGoCamel }}Mock {
tb.Helper()
m := &{{ .InterfaceName | ToGoCamel }}Mock{}
Expand Down Expand Up @@ -687,18 +687,23 @@ func writeImports(writer io.Writer, descPkg PackageDesc) error {
return tmpl.Execute(writer, data)
}

func writeMockBase(writer io.Writer, interfaceName string) error {
func writeMockBase(writer io.Writer, interfaceName string, exported bool) error {
base := template.New("templateMockBase").Funcs(template.FuncMap{
"ToGoCamel": strcase.ToGoCamel,
"ToGoPascal": strcase.ToGoPascal,
})

constructorPrefix := "new"
if exported {
constructorPrefix = "New"
}

tmpl, err := base.Parse(templateMockBase)
if err != nil {
return err
}

return tmpl.Execute(writer, map[string]string{"InterfaceName": interfaceName})
return tmpl.Execute(writer, map[string]interface{}{"InterfaceName": interfaceName, "ConstructorPrefix": constructorPrefix})
}

func quickGoImports(descPkg PackageDesc) []string {
Expand Down
43 changes: 43 additions & 0 deletions testdata/exported/a/a.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package a

import (
"bytes"
"context"
"time"

"golang.org/x/mod/module"
)

type Pineapple interface {
Hello(bar Water) string
World() string
Goo() (string, int, Water)
Coo(context.Context, string, Water) Water
Noo(context.Context) string
}

type Coconut interface {
Boo(src *bytes.Buffer) time.Duration
Doo(src time.Duration) time.Duration
Foo(st Strawberry) string
Goo(st string) Strawberry
Hoo(string, int, Water)
Joo(string, int, Water) (string, int)
Koo(src string) (dst string)
Loo(st string, values ...int) string
Too(src string) time.Duration
Voo(src *module.Version) time.Duration
Yoo(st string) interface{}
Zoo(st interface{}) string
Moo(fn func(st, stban Strawberry) Pineapple) string
}

type Water struct{}

type Strawberry interface {
Bar(string) int
}

type Orange interface {
Juice() <-chan struct{}
}
14 changes: 14 additions & 0 deletions testdata/exported/a/b/b.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package b

import (
"a/c"
)

type Carrot interface {
Bar(string) *Potato
Bur(string) *c.Cherry
}

type Potato struct {
Name string
}
5 changes: 5 additions & 0 deletions testdata/exported/a/c/c.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package c

type Cherry struct {
Name string
}
16 changes: 16 additions & 0 deletions testdata/exported/a/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module a

go 1.18

require (
github.com/stretchr/testify v1.8.0
golang.org/x/mod v0.5.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.4.0 // indirect
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
20 changes: 20 additions & 0 deletions testdata/exported/a/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading

0 comments on commit a041b16

Please sign in to comment.