Skip to content

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
evanphx committed Aug 15, 2018
2 parents 038d9e8 + ec6c1f4 commit 2e43203
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 25 deletions.
12 changes: 9 additions & 3 deletions README.md
Expand Up @@ -4,7 +4,7 @@ mockery
mockery provides the ability to easily generate mocks for golang interfaces. It removes
the boilerplate coding required to use mocks.

[![Linux Build Status](https://travis-ci.org/vektra/mockery.png)](https://travis-ci.org/vektra/mockery) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/vektra/mockery)](https://ci.appveyor.com/project/vektra/mockery) [![GoDoc](https://godoc.org/github.com/vektra/mockery/mockery?status.svg)](https://godoc.org/github.com/vektra/mockery/mockery) [![Go Report Card](https://goreportcard.com/badge/github.com/vektra/mockery)](https://goreportcard.com/report/github.com/vektra/mockery)
[![Linux Build Status](https://travis-ci.org/vektra/mockery.png)](https://travis-ci.org/vektra/mockery) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/vektra/mockery)](https://ci.appveyor.com/project/vektra/mockery) [![GoDoc](https://godoc.org/github.com/vektra/mockery/mockery?status.svg)](https://godoc.org/github.com/vektra/mockery/mockery) [![Go Report Card](https://goreportcard.com/badge/github.com/vektra/mockery)](https://goreportcard.com/report/github.com/vektra/mockery)

### Installation

Expand Down Expand Up @@ -144,8 +144,8 @@ For example, `panic: assert: arguments: Cannot call Get(0) because there are 0 a

#### Notes

This approach should be used judiciously, as return values should generally
not depend on arguments in mocks; however, this approach can be helpful for
This approach should be used judiciously, as return values should generally
not depend on arguments in mocks; however, this approach can be helpful for
situations like passthroughs or other test-only calculations.

### Name
Expand All @@ -170,6 +170,12 @@ This option is only compatible with `-name`. The `-all` option implies `-recursi
mockery always generates files with the package `mocks` to keep things clean and simple.
You can control which mocks directory is used by using `-output`, which defaults to `./mocks`.

### In Package (-inpkg) and KeepTree (-keeptree)

For some complex repositories, there could be multiple interfaces with the same name but in different packages. In that case, `-inpkg` allows generate the mocked interfaces directly in the package that it mocks.

In the case you don't want to generate the mocks into the package but want to keep a similar structure, use the option `-keeptree`.

## Casing

mockery generates files using the casing of the original interface name. This
Expand Down
19 changes: 15 additions & 4 deletions cmd/mockery/mockery.go
Expand Up @@ -29,6 +29,8 @@ type Config struct {
fProfile string
fVersion bool
quiet bool
fkeepTree bool
buildTags string
}

func main() {
Expand Down Expand Up @@ -69,6 +71,10 @@ func main() {
os.Exit(1)
}

if config.fkeepTree {
config.fIP = false
}

if config.fProfile != "" {
f, err := os.Create(config.fProfile)
if err != nil {
Expand All @@ -85,10 +91,12 @@ func main() {
osp = &mockery.StdoutStreamProvider{}
} else {
osp = &mockery.FileOutputStreamProvider{
BaseDir: config.fOutput,
InPackage: config.fIP,
TestOnly: config.fTO,
Case: config.fCase,
BaseDir: config.fOutput,
InPackage: config.fIP,
TestOnly: config.fTO,
Case: config.fCase,
KeepTree: config.fkeepTree,
KeepTreeOriginalDirectory: config.fDir,
}
}

Expand All @@ -104,6 +112,7 @@ func main() {
Recursive: recursive,
Filter: filter,
LimitOne: limitOne,
BuildTags: strings.Split(config.buildTags, " "),
}

generated := walker.Walk(visitor)
Expand Down Expand Up @@ -133,6 +142,8 @@ func parseConfigFromArgs(args []string) Config {
flagSet.StringVar(&config.fProfile, "cpuprofile", "", "write cpu profile to file")
flagSet.BoolVar(&config.fVersion, "version", false, "prints the installed version of mockery")
flagSet.BoolVar(&config.quiet, "quiet", false, "suppress output to stdout")
flagSet.BoolVar(&config.fkeepTree, "keeptree", false, "keep the tree structure of the original interface files into a different repository. Must be used with XX")
flagSet.StringVar(&config.buildTags, "tags", "", "space-separated list of additional build tags to use")

flagSet.Parse(args[1:])

Expand Down
7 changes: 7 additions & 0 deletions mockery/fixtures/buildtag/comment/custom2_iface.go
@@ -0,0 +1,7 @@
// +build custom2

package comment

type IfaceWithCustomBuildTagInComment interface {
Sprintf(format string, a ...interface{}) string
}
7 changes: 7 additions & 0 deletions mockery/fixtures/buildtag/comment/custom_iface.go
@@ -0,0 +1,7 @@
// +build custom

package comment

type IfaceWithCustomBuildTagInComment interface {
Sprintf(format string, a ...interface{}) string
}
7 changes: 7 additions & 0 deletions mockery/fixtures/struct_value.go
@@ -0,0 +1,7 @@
package test

type B struct{}

type A interface {
Call() (B, error)
}
4 changes: 2 additions & 2 deletions mockery/generator.go
Expand Up @@ -267,14 +267,14 @@ func (g *Generator) GeneratePrologue(pkg string) {
// GeneratePrologueNote adds a note after the prologue to the output
// string.
func (g *Generator) GeneratePrologueNote(note string) {
g.printf("// Code generated by mockery v%s\n", SemVer)
g.printf("// Code generated by mockery v%s. DO NOT EDIT.\n", SemVer)
if note != "" {
g.printf("\n")
for _, n := range strings.Split(note, "\\n") {
g.printf("// %s\n", n)
}
g.printf("\n")
}
g.printf("\n")
}

// ErrNotInterface is returned when the given type is not an interface
Expand Down
35 changes: 34 additions & 1 deletion mockery/generator_test.go
Expand Up @@ -254,7 +254,7 @@ func (s *GeneratorSuite) TestGeneratorPrologueNote() {
generator := s.getGenerator(testFile, "Requester", false)
generator.GeneratePrologueNote("A\\nB")

expected := `// Code generated by mockery v1.0.0
expected := `// Code generated by mockery v1.0.0. DO NOT EDIT.
// A
// B
Expand Down Expand Up @@ -1042,6 +1042,39 @@ import test "github.com/vektra/mockery/mockery/fixtures"
s.checkPrologueGeneration(generator, expected)
}

func (s *GeneratorSuite) TestGeneratorForStructValueReturn() {
expected := `// A is an autogenerated mock type for the A type
type A struct {
mock.Mock
}
// Call provides a mock function with given fields:
func (_m *A) Call() (test.B, error) {
ret := _m.Called()
var r0 test.B
if rf, ok := ret.Get(0).(func() test.B); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(test.B)
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
`
s.checkGeneration(
filepath.Join(fixturePath, "struct_value.go"), "A", false,
expected,
)
}

func TestGeneratorSuite(t *testing.T) {
generatorSuite := new(GeneratorSuite)
suite.Run(t, generatorSuite)
Expand Down
24 changes: 18 additions & 6 deletions mockery/outputter.go
Expand Up @@ -23,10 +23,12 @@ func (this *StdoutStreamProvider) GetWriter(iface *Interface, pkg string) (io.Wr
}

type FileOutputStreamProvider struct {
BaseDir string
InPackage bool
TestOnly bool
Case string
BaseDir string
InPackage bool
TestOnly bool
Case string
KeepTree bool
KeepTreeOriginalDirectory string
}

func (this *FileOutputStreamProvider) GetWriter(iface *Interface, pkg string) (io.Writer, error, Cleanup) {
Expand All @@ -37,7 +39,17 @@ func (this *FileOutputStreamProvider) GetWriter(iface *Interface, pkg string) (i
caseName = this.underscoreCaseName(caseName)
}

if this.InPackage {
if this.KeepTree {
absOriginalDir, err := filepath.Abs(this.KeepTreeOriginalDirectory)
if err != nil {
return nil, err, func() error { return nil }
}
relativePath := strings.TrimPrefix(
filepath.Join(filepath.Dir(iface.Path), this.filename(caseName)),
absOriginalDir)
path = filepath.Join(this.BaseDir, relativePath)
os.MkdirAll(filepath.Dir(path), 0755)
} else if this.InPackage {
path = filepath.Join(filepath.Dir(iface.Path), this.filename(caseName))
} else {
path = filepath.Join(this.BaseDir, this.filename(caseName))
Expand All @@ -50,7 +62,7 @@ func (this *FileOutputStreamProvider) GetWriter(iface *Interface, pkg string) (i
return nil, err, func() error { return nil }
}

fmt.Printf("Generating mock for: %s\n", iface.Name)
fmt.Printf("Generating mock for: %s in file: %s\n", iface.Name, path)
return f, nil, func() error {
return f.Close()
}
Expand Down
13 changes: 6 additions & 7 deletions mockery/parse.go
Expand Up @@ -31,8 +31,8 @@ func NewParser() *Parser {

// Initialize the build context (e.g. GOARCH/GOOS fields) so we can use it for respecting
// build tags during Parse.
defaultBuildCtx := build.Default
conf.Build = &defaultBuildCtx
buildCtx := build.Default
conf.Build = &buildCtx

return &Parser{
parserPackages: make([]*types.Package, 0),
Expand All @@ -43,6 +43,10 @@ func NewParser() *Parser {
}
}

func (p *Parser) AddBuildTags(buildTags ...string) {
p.conf.Build.BuildTags = append(p.conf.Build.BuildTags, buildTags...)
}

func (p *Parser) Parse(path string) error {

// To support relative paths to mock targets w/ vendor deps, we need to provide eventual
Expand All @@ -57,11 +61,6 @@ func (p *Parser) Parse(path string) error {
return err
}

path, err = filepath.EvalSymlinks(path)
if err != nil {
return err
}

dir := filepath.Dir(path)

files, err := ioutil.ReadDir(dir)
Expand Down
19 changes: 19 additions & 0 deletions mockery/parse_test.go
Expand Up @@ -85,3 +85,22 @@ func TestBuildTagInComment(t *testing.T) {
assert.Equal(t, 1, len(nodes))
assert.Equal(t, "IfaceWithBuildTagInComment", nodes[0].Name)
}

func TestCustomBuildTag(t *testing.T) {
parser := NewParser()
parser.AddBuildTags("custom")

// Include two files that define the same interface, but with different
// build tags. Only one should be loaded.
err := parser.Parse(getFixturePath("buildtag", "comment", "custom_iface.go"))
assert.NoError(t, err)
err = parser.Parse(getFixturePath("buildtag", "comment", "custom2_iface.go"))
assert.NoError(t, err)

err = parser.Load()
assert.NoError(t, err) // Expect "redeclared in this block" if tags aren't respected

nodes := parser.Interfaces()
assert.Equal(t, 1, len(nodes))
assert.Equal(t, "IfaceWithCustomBuildTagInComment", nodes[0].Name)
}
2 changes: 2 additions & 0 deletions mockery/walker.go
Expand Up @@ -15,6 +15,7 @@ type Walker struct {
Recursive bool
Filter *regexp.Regexp
LimitOne bool
BuildTags []string
}

type WalkerVisitor interface {
Expand All @@ -23,6 +24,7 @@ type WalkerVisitor interface {

func (this *Walker) Walk(visitor WalkerVisitor) (generated bool) {
parser := NewParser()
parser.AddBuildTags(this.BuildTags...)
this.doWalk(parser, this.BaseDir, visitor)

err := parser.Load()
Expand Down
4 changes: 2 additions & 2 deletions mockery/walker_test.go
Expand Up @@ -43,8 +43,8 @@ func TestWalkerHere(t *testing.T) {

assert.True(t, len(gv.Interfaces) > 10)
first := gv.Interfaces[0]
assert.Equal(t, "AsyncProducer", first.Name)
assert.Equal(t, getFixturePath("async.go"), first.Path)
assert.Equal(t, "A", first.Name)
assert.Equal(t, getFixturePath("struct_value.go"), first.Path)
}

func TestWalkerRegexp(t *testing.T) {
Expand Down

0 comments on commit 2e43203

Please sign in to comment.