diff --git a/.golangci.yml b/.golangci.yml index 4bdaa01..baa398f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -89,6 +89,10 @@ issues: linters: - funlen - noctx + - path: mocktail.go + linters: + - gocyclo + text: "cyclomatic complexity 16 of func `processSingleFile` is high" # The complexity is expected. output: show-stats: true diff --git a/mocktail.go b/mocktail.go index 8370945..9cd0323 100644 --- a/mocktail.go +++ b/mocktail.go @@ -48,7 +48,11 @@ func main() { } var exported bool + var sourceFile string + var interfaceNames string flag.BoolVar(&exported, "e", false, "generate exported mocks") + flag.StringVar(&sourceFile, "source", "", "source file containing interfaces to mock") + flag.StringVar(&interfaceNames, "interface", "", "comma-separated list of interface names to mock (used with -source), mock every interface by default (has no effect without -source)") flag.Parse() root := info.Dir @@ -58,9 +62,17 @@ func main() { log.Fatalf("Chdir: %v", err) } - model, err := walk(root, info.Path) - if err != nil { - log.Fatalf("walk: %v", err) + var model map[string]PackageDesc + if sourceFile != "" { + model, err = processSingleFile(sourceFile, root, info.Path, interfaceNames) + if err != nil { + log.Fatalf("process single file: %v", err) + } + } else { + model, err = walk(root, info.Path) + if err != nil { + log.Fatalf("walk: %v", err) + } } if len(model) == 0 { @@ -73,6 +85,163 @@ func main() { } } +// processSingleFile processes a single source file to extract interfaces for mocking. +func processSingleFile(sourceFile, root, moduleName, interfaceFilter string) (map[string]PackageDesc, error) { + model := make(map[string]PackageDesc) + + // Convert to absolute path if relative + if !filepath.IsAbs(sourceFile) { + sourceFile = filepath.Join(os.Getenv("PWD"), sourceFile) + } + + // Check if file exists + if _, err := os.Stat(sourceFile); os.IsNotExist(err) { + return nil, fmt.Errorf("source file does not exist: %s", sourceFile) + } + + // Parse interface filter if provided + targetInterfaces := parseInterfaceFilter(interfaceFilter) + + // Load package from source file + pkg, err := loadPackageFromFile(sourceFile, root, moduleName) + if err != nil { + return nil, fmt.Errorf("load package from file: %w", err) + } + + if pkg == nil { + return model, nil // Return empty model when no packages found + } + + // Process interfaces in the package + packageDesc := processPackageInterfaces(pkg, targetInterfaces) + + if len(packageDesc.Interfaces) > 0 { + // Use the source file path as the key, but change the filename to match expected output location + outputDir := filepath.Dir(sourceFile) + outputKey := filepath.Join(outputDir, srcMockFile) + model[outputKey] = packageDesc + } + + return model, nil +} + +// parseInterfaceFilter parses the interface filter string into a map of target interfaces. +func parseInterfaceFilter(interfaceFilter string) map[string]struct{} { + if interfaceFilter == "" { + return nil + } + + targetInterfaces := make(map[string]struct{}) + for _, name := range strings.Split(interfaceFilter, ",") { + name = strings.TrimSpace(name) + if name != "" { + targetInterfaces[name] = struct{}{} + } + } + + return targetInterfaces +} + +// loadPackageFromFile loads a Go package from a source file. +func loadPackageFromFile(sourceFile, root, moduleName string) (*types.Package, error) { + // Get the package path for this file + fileDir := filepath.Dir(sourceFile) + + // Load the package + pkgs, err := packages.Load( + &packages.Config{ + Mode: packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedFiles, + Dir: fileDir, + }, + ".", + ) + if err != nil { + return nil, fmt.Errorf("load package: %w", err) + } + + if len(pkgs) == 0 { + return nil, nil + } + + pkg := pkgs[0] + if pkg.Types == nil { + relDir, err := filepath.Rel(root, fileDir) + if err != nil { + return nil, fmt.Errorf("get relative directory: %w", err) + } + + return nil, fmt.Errorf("package %q has no type information", path.Join(moduleName, relDir)) + } + + return pkg.Types, nil +} + +// processPackageInterfaces processes all interfaces in a package, optionally filtering by target interfaces. +func processPackageInterfaces(pkg *types.Package, targetInterfaces map[string]struct{}) PackageDesc { + packageDesc := PackageDesc{ + Pkg: pkg, + Imports: map[string]struct{}{}, + } + + scope := pkg.Scope() + for _, name := range scope.Names() { + obj := scope.Lookup(name) + if obj == nil { + continue + } + + // If interface filter is specified, only process those interfaces + if targetInterfaces != nil { + if _, wanted := targetInterfaces[name]; !wanted { + continue + } + } + + // Check if it's an interface and process it + interfaceDesc := processInterfaceType(name, obj) + + if interfaceDesc != nil { + packageDesc.Interfaces = append(packageDesc.Interfaces, *interfaceDesc) + // Collect imports from the interface methods + for _, method := range interfaceDesc.Methods { + for _, imp := range getMethodImports(method, pkg.Path()) { + packageDesc.Imports[imp] = struct{}{} + } + } + } + } + + return packageDesc +} + +// processInterfaceType processes a single type to check if it's an interface and extract its methods. +func processInterfaceType(name string, obj types.Object) *InterfaceDesc { + // Check if it's an interface + named, ok := obj.Type().(*types.Named) + if !ok { + return nil + } + + interfaceType, ok := named.Underlying().(*types.Interface) + if !ok { + return nil + } + + interfaceDesc := InterfaceDesc{Name: name} + + // Get all methods from the interface + for i := range interfaceType.NumMethods() { + method := interfaceType.Method(i) + interfaceDesc.Methods = append(interfaceDesc.Methods, method) + } + + if len(interfaceDesc.Methods) == 0 { + return nil + } + + return &interfaceDesc +} + //nolint:gocognit,gocyclo // The complexity is expected. func walk(root, moduleName string) (map[string]PackageDesc, error) { model := make(map[string]PackageDesc) diff --git a/mocktail_test.go b/mocktail_test.go index c6968bc..7313704 100644 --- a/mocktail_test.go +++ b/mocktail_test.go @@ -12,10 +12,12 @@ import ( "github.com/stretchr/testify/require" ) +const goosWindows = "windows" + func TestMocktail(t *testing.T) { const testRoot = "./testdata/src" - if runtime.GOOS == "windows" { + if runtime.GOOS == goosWindows { t.Skip(runtime.GOOS) } @@ -74,7 +76,7 @@ func TestMocktail(t *testing.T) { func TestMocktail_exported(t *testing.T) { const testRoot = "./testdata/exported" - if runtime.GOOS == "windows" { + if runtime.GOOS == goosWindows { t.Skip(runtime.GOOS) } @@ -129,3 +131,378 @@ func TestMocktail_exported(t *testing.T) { require.NoError(t, err) } } + +func TestMocktail_source(t *testing.T) { + const testRoot = "./testdata/source" + + if runtime.GOOS == goosWindows { + t.Skip(runtime.GOOS) + } + + testCases := []struct { + name string + expectedOutput string + extraArgs []string + }{ + { + name: "a", + expectedOutput: outputMockFile, + extraArgs: nil, + }, + { + name: "b", + expectedOutput: outputExportedMockFile, + extraArgs: []string{"-e"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + testDir := filepath.Join(testRoot, tc.name) + interfacesFile := filepath.Join(testDir, "interfaces.go") + + // Convert to absolute path to avoid path duplication issues + absTestDir, err := filepath.Abs(testDir) + require.NoError(t, err) + absInterfacesFile, err := filepath.Abs(interfacesFile) + require.NoError(t, err) + + // Set up environment + t.Setenv("MOCKTAIL_TEST_PATH", absTestDir) + + // Build command args + args := []string{"run", "."} + args = append(args, tc.extraArgs...) + args = append(args, "-source="+absInterfacesFile) + + // Run mocktail with source parameter + output, err := exec.Command("go", args...).CombinedOutput() + t.Log(string(output)) + require.NoError(t, err) + + // Check generated file matches golden file + genPath := filepath.Join(testDir, tc.expectedOutput) + t.Cleanup(func() { + _ = os.Remove(genPath) + }) + + goldenPath := genPath + ".golden" + + genBytes, err := os.ReadFile(genPath) + require.NoError(t, err) + + goldenBytes, err := os.ReadFile(goldenPath) + require.NoError(t, err) + + assert.Equal(t, string(goldenBytes), string(genBytes)) + + cmd := exec.Command("go", "test", "-v", "./...") + cmd.Dir = testDir + + output, err = cmd.CombinedOutput() + t.Log(string(output)) + require.NoError(t, err) + }) + } +} + +func TestProcessSingleFile(t *testing.T) { + t.Parallel() + + if runtime.GOOS == goosWindows { + t.Skip(runtime.GOOS) + } + + tests := []struct { + name string + sourceFile string + interfaceFilter string + expectedErr bool + expectedIntf int // expected number of interfaces + expectedModels int // expected number of models + }{ + { + name: "valid_basic_file_all_interfaces", + sourceFile: "testdata/source/a/interfaces.go", + interfaceFilter: "", + expectedErr: false, + expectedIntf: 2, // PiniaColada, shirleyTemple + expectedModels: 1, + }, + { + name: "valid_basic_file_single_interface", + sourceFile: "testdata/source/a/interfaces.go", + interfaceFilter: "PiniaColada", + expectedErr: false, + expectedIntf: 1, // PiniaColada only + expectedModels: 1, + }, + { + name: "valid_basic_file_multiple_interfaces", + sourceFile: "testdata/source/a/interfaces.go", + interfaceFilter: "PiniaColada,shirleyTemple", + expectedErr: false, + expectedIntf: 2, // Both interfaces + expectedModels: 1, + }, + { + name: "valid_exported_file", + sourceFile: "testdata/source/b/interfaces.go", + interfaceFilter: "", + expectedErr: false, + expectedIntf: 1, // PiniaColada + expectedModels: 1, + }, + { + name: "valid_exported_file_specific_interface", + sourceFile: "testdata/source/b/interfaces.go", + interfaceFilter: "PiniaColada", + expectedErr: false, + expectedIntf: 1, // PiniaColada + expectedModels: 1, + }, + { + name: "nonexistent_file", + sourceFile: "testdata/source/nonexistent.go", + interfaceFilter: "", + expectedErr: true, + expectedModels: 0, + }, + { + name: "relative_path", + sourceFile: "./testdata/source/a/interfaces.go", + interfaceFilter: "", + expectedErr: false, + expectedIntf: 2, // PiniaColada, shirleyTemple + expectedModels: 1, + }, + { + name: "nonexistent_interface", + sourceFile: "testdata/source/a/interfaces.go", + interfaceFilter: "NonExistentInterface", + expectedIntf: 0, // No interfaces found + expectedModels: 0, + }, + { + name: "partial_nonexistent_interface", + sourceFile: "testdata/source/a/interfaces.go", + interfaceFilter: "PiniaColada,NonExistentInterface", + expectedIntf: 1, // PiniaColada only + expectedModels: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Convert source file to absolute path to avoid path issues + absSourceFile, err := filepath.Abs(tt.sourceFile) + if !tt.expectedErr { + require.NoError(t, err) + } + + // Get the module info for the specific test directory + testDir := filepath.Dir(absSourceFile) + info, err := getModuleInfo(testDir) + if !tt.expectedErr { + require.NoError(t, err) + } + + // Test processSingleFile function + model, err := processSingleFile(absSourceFile, info.Dir, info.Path, tt.interfaceFilter) + + if tt.expectedErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + + // Should have exactly one entry in the model + assert.Len(t, model, tt.expectedModels) + + // Check the number of interfaces found + var totalInterfaces int + for _, pkgDesc := range model { + totalInterfaces += len(pkgDesc.Interfaces) + } + assert.Equal(t, tt.expectedIntf, totalInterfaces) + + // Verify interfaces have methods + for _, pkgDesc := range model { + for _, intf := range pkgDesc.Interfaces { + assert.NotEmpty(t, intf.Methods, "Interface %s should have methods", intf.Name) + } + } + }) + } +} + +func TestProcessSingleFile_InvalidPackage(t *testing.T) { + t.Parallel() + + if runtime.GOOS == goosWindows { + t.Skip(runtime.GOOS) + } + + // Create a temporary file with invalid Go code + tmpFile, err := os.CreateTemp(t.TempDir(), "invalid_*.go") + require.NoError(t, err) + t.Cleanup(func() { + _ = os.Remove(tmpFile.Name()) + }) + + _, err = tmpFile.WriteString("package invalid\n\n// This is not a valid interface\ntype NotAnInterface struct{}\n") + require.NoError(t, err) + _ = tmpFile.Close() + + // Use current directory for temporary file test + cwd, err := os.Getwd() + require.NoError(t, err) + info, err := getModuleInfo(cwd) + require.NoError(t, err) + + // Test processSingleFile with file containing no interfaces + model, err := processSingleFile(tmpFile.Name(), info.Dir, info.Path, "") + require.NoError(t, err) + assert.Empty(t, model, "Should return empty model when no interfaces found") +} + +func TestProcessSingleFile_AbsolutePath(t *testing.T) { + t.Parallel() + + if runtime.GOOS == goosWindows { + t.Skip(runtime.GOOS) + } + + // Test with absolute path + absPath, err := filepath.Abs("testdata/source/a/interfaces.go") + require.NoError(t, err) + + // Get module info from the test directory + testDir := filepath.Dir(absPath) + info, err := getModuleInfo(testDir) + require.NoError(t, err) + + model, err := processSingleFile(absPath, info.Dir, info.Path, "") + require.NoError(t, err) + + assert.Len(t, model, 1) + + var totalInterfaces int + for _, pkgDesc := range model { + totalInterfaces += len(pkgDesc.Interfaces) + } + assert.Equal(t, 2, totalInterfaces) +} + +func TestMocktail_interface_flag(t *testing.T) { + if runtime.GOOS == goosWindows { + t.Skip(runtime.GOOS) + } + + testCases := []struct { + name string + sourceFile string + interfaceFilter string + expectedOutput string + extraArgs []string + checkContent bool // Whether to check the content of the generated file + }{ + { + name: "single_interface", + sourceFile: "./testdata/source/a/interfaces.go", + interfaceFilter: "PiniaColada", + expectedOutput: outputMockFile, + extraArgs: nil, + checkContent: true, + }, + { + name: "single_interface_exported", + sourceFile: "./testdata/source/a/interfaces.go", + interfaceFilter: "PiniaColada", + expectedOutput: outputExportedMockFile, + extraArgs: []string{"-e"}, + checkContent: true, + }, + { + name: "multiple_interfaces", + sourceFile: "./testdata/source/a/interfaces.go", + interfaceFilter: "PiniaColada,shirleyTemple", + expectedOutput: outputMockFile, + extraArgs: nil, + checkContent: false, // This one can run the full test since it has both interfaces + }, + { + name: "all_interfaces_no_filter", + sourceFile: "./testdata/source/a/interfaces.go", + interfaceFilter: "", + expectedOutput: outputMockFile, + extraArgs: nil, + checkContent: false, // This one can run the full test since it has both interfaces + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Get current working directory (project root) + cwd, err := os.Getwd() + require.NoError(t, err) + + // Set up environment to use current directory as root + t.Setenv("MOCKTAIL_TEST_PATH", cwd) + + // Build command args + args := []string{"run", "."} + args = append(args, tc.extraArgs...) + args = append(args, "-source="+tc.sourceFile) + if tc.interfaceFilter != "" { + args = append(args, "-interface="+tc.interfaceFilter) + } + + // Run mocktail with interface parameter from project root + cmd := exec.Command("go", args...) + cmd.Dir = cwd + output, err := cmd.CombinedOutput() + t.Log(string(output)) + require.NoError(t, err) + + // Check generated file exists in the correct location + genPath := filepath.Join(cwd, "testdata", "source", "a", tc.expectedOutput) + t.Cleanup(func() { + _ = os.Remove(genPath) + }) + + _, err = os.Stat(genPath) + require.NoError(t, err, "Generated file should exist at %s", genPath) + + if tc.checkContent { + // Just verify the file contains the expected interface mock + content, errRead := os.ReadFile(genPath) + require.NoError(t, errRead) + + // Check that the file contains the expected mock structure + contentStr := string(content) + assert.Contains(t, contentStr, "piniaColadaMock", "Generated file should contain PiniaColada mock") + assert.Contains(t, contentStr, "OnRhum", "Generated file should contain OnRhum method") + assert.Contains(t, contentStr, "OnPine", "Generated file should contain OnPine method") + assert.Contains(t, contentStr, "OnCoconut", "Generated file should contain OnCoconut method") + + // If filtering for single interface, should not contain the other interface + if tc.interfaceFilter == "PiniaColada" { + assert.NotContains(t, contentStr, "shirleyTempleMock", "Should not contain shirleyTemple mock when filtering for PiniaColada only") + } + + return + } + + // For the multiple interfaces test, run the full test suite + testDir := filepath.Join(cwd, "testdata", "source", "a") + testCmd := exec.Command("go", "test", "-v", "./...") + testCmd.Dir = testDir + + output, err = testCmd.CombinedOutput() + t.Log(string(output)) + require.NoError(t, err) + }) + } +} diff --git a/readme.md b/readme.md index 4ebe006..3f06b67 100644 --- a/readme.md +++ b/readme.md @@ -26,6 +26,84 @@ package example ``` +## Single File Mode with go:generate + +You can also use Mocktail with `//go:generate` comments to generate mocks for interfaces in a specific file using the `-source` parameter: + +### Usage + +Create a file with your interfaces: + +```go +// interfaces.go +package main + +import ( + "context" + "io" +) + +type UserService interface { + GetUser(ctx context.Context, id string) (*User, error) + CreateUser(ctx context.Context, user *User) error +} + +type FileHandler interface { + Upload(ctx context.Context, filename string, content io.Reader) error + Download(ctx context.Context, filename string) (io.ReadCloser, error) +} + +type User struct { + ID string `json:"id"` + Name string `json:"name"` + Email string `json:"email"` +} +``` + +Add a `//go:generate` comment in any Go file in the same package: + +```go +// main.go +package main + +//go:generate mocktail -source=interfaces.go + +func main() { + // Your application code +} +``` + +Then run: + +```bash +go generate +``` + +This will generate `mock_gen_test.go` containing mocks for all exported interfaces in the specified source file. + +### Selective Interface Mocking + +You can specify which interfaces to mock from a source file using the `-interface` flag in combination with `-source`: + +```bash +# Mock only specific interfaces from a file +mocktail -source=interfaces.go -interface="UserService,FileHandler" + +# Mock a single interface +mocktail -source=interfaces.go -interface="UserService" +``` + +The `-interface` flag accepts a comma-separated list of interface names and can only be used together with the `-source` flag. + +### Options + +- **Regular mocks**: `mocktail -source=interfaces.go` (generates `mock_gen_test.go`) +- **Exported mocks**: `mocktail -source=interfaces.go -e` (generates `mock_gen.go`) +- **Specific interfaces**: `mocktail -source=interfaces.go -interface="Interface1,Interface2"` +- **Exported + Specific**: `mocktail -source=interfaces.go -e -interface="ClientInterface"` + +The `-source` parameter accepts both relative paths (relative to the current working directory) and absolute paths. + ## How to Install ### Go Install @@ -40,9 +118,9 @@ go install github.com/traefik/mocktail@latest You can use pre-compiled binaries: -* To get the binary just download the latest release for your OS/Arch from [the releases page](https://github.com/traefik/mocktail/releases) -* Unzip the archive. -* Add `mocktail` in your `PATH`. +- To get the binary just download the latest release for your OS/Arch from [the releases page](https://github.com/traefik/mocktail/releases) +- Unzip the archive. +- Add `mocktail` in your `PATH`. ## Notes @@ -50,7 +128,7 @@ It requires testify >= v1.7.0 Mocktail can only generate mock of interfaces inside a module itself (not from stdlib or dependencies) -The `// mocktail` comments **must** be added to a file named `mock_test.go` only, +The `// mocktail` comments **must** be added to a file named `mock_test.go` only, comments in other files will not be detected ## Examples diff --git a/testdata/source/a/go.mod b/testdata/source/a/go.mod new file mode 100644 index 0000000..627f9ee --- /dev/null +++ b/testdata/source/a/go.mod @@ -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 +) diff --git a/testdata/source/a/go.sum b/testdata/source/a/go.sum new file mode 100644 index 0000000..0c98ef7 --- /dev/null +++ b/testdata/source/a/go.sum @@ -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= diff --git a/testdata/source/a/interfaces.go b/testdata/source/a/interfaces.go new file mode 100644 index 0000000..3a855d1 --- /dev/null +++ b/testdata/source/a/interfaces.go @@ -0,0 +1,13 @@ +package a + +type PiniaColada interface { + Rhum() string + Pine(apple string) + Coconut() +} + +type shirleyTemple interface { + ale(ginger string) + Grenadine() + GetCherry() (maraschino string) +} \ No newline at end of file diff --git a/testdata/source/a/mock_gen_test.go.golden b/testdata/source/a/mock_gen_test.go.golden new file mode 100644 index 0000000..0147d7b --- /dev/null +++ b/testdata/source/a/mock_gen_test.go.golden @@ -0,0 +1,606 @@ +// Code generated by mocktail; DO NOT EDIT. + +package a + +import ( + "testing" + "time" + + "github.com/stretchr/testify/mock" +) + +// piniaColadaMock mock of PiniaColada. +type piniaColadaMock struct{ mock.Mock } + +// newPiniaColadaMock creates a new piniaColadaMock. +func newPiniaColadaMock(tb testing.TB) *piniaColadaMock { + tb.Helper() + + m := &piniaColadaMock{} + m.Mock.Test(tb) + + tb.Cleanup(func() { m.AssertExpectations(tb) }) + + return m +} + +func (_m *piniaColadaMock) Coconut() { + _m.Called() +} + +func (_m *piniaColadaMock) OnCoconut() *piniaColadaCoconutCall { + return &piniaColadaCoconutCall{Call: _m.Mock.On("Coconut"), Parent: _m} +} + +func (_m *piniaColadaMock) OnCoconutRaw() *piniaColadaCoconutCall { + return &piniaColadaCoconutCall{Call: _m.Mock.On("Coconut"), Parent: _m} +} + +type piniaColadaCoconutCall struct { + *mock.Call + Parent *piniaColadaMock +} + +func (_c *piniaColadaCoconutCall) Panic(msg string) *piniaColadaCoconutCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *piniaColadaCoconutCall) Once() *piniaColadaCoconutCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *piniaColadaCoconutCall) Twice() *piniaColadaCoconutCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *piniaColadaCoconutCall) Times(i int) *piniaColadaCoconutCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *piniaColadaCoconutCall) WaitUntil(w <-chan time.Time) *piniaColadaCoconutCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *piniaColadaCoconutCall) After(d time.Duration) *piniaColadaCoconutCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *piniaColadaCoconutCall) Run(fn func(args mock.Arguments)) *piniaColadaCoconutCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *piniaColadaCoconutCall) Maybe() *piniaColadaCoconutCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *piniaColadaCoconutCall) TypedRun(fn func()) *piniaColadaCoconutCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + fn() + }) + return _c +} + +func (_c *piniaColadaCoconutCall) OnCoconut() *piniaColadaCoconutCall { + return _c.Parent.OnCoconut() +} + +func (_c *piniaColadaCoconutCall) OnPine(apple string) *piniaColadaPineCall { + return _c.Parent.OnPine(apple) +} + +func (_c *piniaColadaCoconutCall) OnRhum() *piniaColadaRhumCall { + return _c.Parent.OnRhum() +} + +func (_c *piniaColadaCoconutCall) OnCoconutRaw() *piniaColadaCoconutCall { + return _c.Parent.OnCoconutRaw() +} + +func (_c *piniaColadaCoconutCall) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return _c.Parent.OnPineRaw(apple) +} + +func (_c *piniaColadaCoconutCall) OnRhumRaw() *piniaColadaRhumCall { + return _c.Parent.OnRhumRaw() +} + +func (_m *piniaColadaMock) Pine(apple string) { + _m.Called(apple) +} + +func (_m *piniaColadaMock) OnPine(apple string) *piniaColadaPineCall { + return &piniaColadaPineCall{Call: _m.Mock.On("Pine", apple), Parent: _m} +} + +func (_m *piniaColadaMock) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return &piniaColadaPineCall{Call: _m.Mock.On("Pine", apple), Parent: _m} +} + +type piniaColadaPineCall struct { + *mock.Call + Parent *piniaColadaMock +} + +func (_c *piniaColadaPineCall) Panic(msg string) *piniaColadaPineCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *piniaColadaPineCall) Once() *piniaColadaPineCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *piniaColadaPineCall) Twice() *piniaColadaPineCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *piniaColadaPineCall) Times(i int) *piniaColadaPineCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *piniaColadaPineCall) WaitUntil(w <-chan time.Time) *piniaColadaPineCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *piniaColadaPineCall) After(d time.Duration) *piniaColadaPineCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *piniaColadaPineCall) Run(fn func(args mock.Arguments)) *piniaColadaPineCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *piniaColadaPineCall) Maybe() *piniaColadaPineCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *piniaColadaPineCall) TypedRun(fn func(string)) *piniaColadaPineCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + _apple := args.String(0) + fn(_apple) + }) + return _c +} + +func (_c *piniaColadaPineCall) OnCoconut() *piniaColadaCoconutCall { + return _c.Parent.OnCoconut() +} + +func (_c *piniaColadaPineCall) OnPine(apple string) *piniaColadaPineCall { + return _c.Parent.OnPine(apple) +} + +func (_c *piniaColadaPineCall) OnRhum() *piniaColadaRhumCall { + return _c.Parent.OnRhum() +} + +func (_c *piniaColadaPineCall) OnCoconutRaw() *piniaColadaCoconutCall { + return _c.Parent.OnCoconutRaw() +} + +func (_c *piniaColadaPineCall) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return _c.Parent.OnPineRaw(apple) +} + +func (_c *piniaColadaPineCall) OnRhumRaw() *piniaColadaRhumCall { + return _c.Parent.OnRhumRaw() +} + +func (_m *piniaColadaMock) Rhum() string { + _ret := _m.Called() + + if _rf, ok := _ret.Get(0).(func() string); ok { + return _rf() + } + + _ra0 := _ret.String(0) + + return _ra0 +} + +func (_m *piniaColadaMock) OnRhum() *piniaColadaRhumCall { + return &piniaColadaRhumCall{Call: _m.Mock.On("Rhum"), Parent: _m} +} + +func (_m *piniaColadaMock) OnRhumRaw() *piniaColadaRhumCall { + return &piniaColadaRhumCall{Call: _m.Mock.On("Rhum"), Parent: _m} +} + +type piniaColadaRhumCall struct { + *mock.Call + Parent *piniaColadaMock +} + +func (_c *piniaColadaRhumCall) Panic(msg string) *piniaColadaRhumCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *piniaColadaRhumCall) Once() *piniaColadaRhumCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *piniaColadaRhumCall) Twice() *piniaColadaRhumCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *piniaColadaRhumCall) Times(i int) *piniaColadaRhumCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *piniaColadaRhumCall) WaitUntil(w <-chan time.Time) *piniaColadaRhumCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *piniaColadaRhumCall) After(d time.Duration) *piniaColadaRhumCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *piniaColadaRhumCall) Run(fn func(args mock.Arguments)) *piniaColadaRhumCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *piniaColadaRhumCall) Maybe() *piniaColadaRhumCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *piniaColadaRhumCall) TypedReturns(a string) *piniaColadaRhumCall { + _c.Call = _c.Return(a) + return _c +} + +func (_c *piniaColadaRhumCall) ReturnsFn(fn func() string) *piniaColadaRhumCall { + _c.Call = _c.Return(fn) + return _c +} + +func (_c *piniaColadaRhumCall) TypedRun(fn func()) *piniaColadaRhumCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + fn() + }) + return _c +} + +func (_c *piniaColadaRhumCall) OnCoconut() *piniaColadaCoconutCall { + return _c.Parent.OnCoconut() +} + +func (_c *piniaColadaRhumCall) OnPine(apple string) *piniaColadaPineCall { + return _c.Parent.OnPine(apple) +} + +func (_c *piniaColadaRhumCall) OnRhum() *piniaColadaRhumCall { + return _c.Parent.OnRhum() +} + +func (_c *piniaColadaRhumCall) OnCoconutRaw() *piniaColadaCoconutCall { + return _c.Parent.OnCoconutRaw() +} + +func (_c *piniaColadaRhumCall) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return _c.Parent.OnPineRaw(apple) +} + +func (_c *piniaColadaRhumCall) OnRhumRaw() *piniaColadaRhumCall { + return _c.Parent.OnRhumRaw() +} + +// shirleyTempleMock mock of shirleyTemple. +type shirleyTempleMock struct{ mock.Mock } + +// newShirleyTempleMock creates a new shirleyTempleMock. +func newShirleyTempleMock(tb testing.TB) *shirleyTempleMock { + tb.Helper() + + m := &shirleyTempleMock{} + m.Mock.Test(tb) + + tb.Cleanup(func() { m.AssertExpectations(tb) }) + + return m +} + +func (_m *shirleyTempleMock) GetCherry() string { + _ret := _m.Called() + + if _rf, ok := _ret.Get(0).(func() string); ok { + return _rf() + } + + maraschino := _ret.String(0) + + return maraschino +} + +func (_m *shirleyTempleMock) OnGetCherry() *shirleyTempleGetCherryCall { + return &shirleyTempleGetCherryCall{Call: _m.Mock.On("GetCherry"), Parent: _m} +} + +func (_m *shirleyTempleMock) OnGetCherryRaw() *shirleyTempleGetCherryCall { + return &shirleyTempleGetCherryCall{Call: _m.Mock.On("GetCherry"), Parent: _m} +} + +type shirleyTempleGetCherryCall struct { + *mock.Call + Parent *shirleyTempleMock +} + +func (_c *shirleyTempleGetCherryCall) Panic(msg string) *shirleyTempleGetCherryCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *shirleyTempleGetCherryCall) Once() *shirleyTempleGetCherryCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *shirleyTempleGetCherryCall) Twice() *shirleyTempleGetCherryCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *shirleyTempleGetCherryCall) Times(i int) *shirleyTempleGetCherryCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *shirleyTempleGetCherryCall) WaitUntil(w <-chan time.Time) *shirleyTempleGetCherryCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *shirleyTempleGetCherryCall) After(d time.Duration) *shirleyTempleGetCherryCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *shirleyTempleGetCherryCall) Run(fn func(args mock.Arguments)) *shirleyTempleGetCherryCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *shirleyTempleGetCherryCall) Maybe() *shirleyTempleGetCherryCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *shirleyTempleGetCherryCall) TypedReturns(a string) *shirleyTempleGetCherryCall { + _c.Call = _c.Return(a) + return _c +} + +func (_c *shirleyTempleGetCherryCall) ReturnsFn(fn func() string) *shirleyTempleGetCherryCall { + _c.Call = _c.Return(fn) + return _c +} + +func (_c *shirleyTempleGetCherryCall) TypedRun(fn func()) *shirleyTempleGetCherryCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + fn() + }) + return _c +} + +func (_c *shirleyTempleGetCherryCall) OnGetCherry() *shirleyTempleGetCherryCall { + return _c.Parent.OnGetCherry() +} + +func (_c *shirleyTempleGetCherryCall) OnGrenadine() *shirleyTempleGrenadineCall { + return _c.Parent.OnGrenadine() +} + +func (_c *shirleyTempleGetCherryCall) Onale(ginger string) *shirleyTemplealeCall { + return _c.Parent.Onale(ginger) +} + +func (_c *shirleyTempleGetCherryCall) OnGetCherryRaw() *shirleyTempleGetCherryCall { + return _c.Parent.OnGetCherryRaw() +} + +func (_c *shirleyTempleGetCherryCall) OnGrenadineRaw() *shirleyTempleGrenadineCall { + return _c.Parent.OnGrenadineRaw() +} + +func (_c *shirleyTempleGetCherryCall) OnaleRaw(ginger interface{}) *shirleyTemplealeCall { + return _c.Parent.OnaleRaw(ginger) +} + +func (_m *shirleyTempleMock) Grenadine() { + _m.Called() +} + +func (_m *shirleyTempleMock) OnGrenadine() *shirleyTempleGrenadineCall { + return &shirleyTempleGrenadineCall{Call: _m.Mock.On("Grenadine"), Parent: _m} +} + +func (_m *shirleyTempleMock) OnGrenadineRaw() *shirleyTempleGrenadineCall { + return &shirleyTempleGrenadineCall{Call: _m.Mock.On("Grenadine"), Parent: _m} +} + +type shirleyTempleGrenadineCall struct { + *mock.Call + Parent *shirleyTempleMock +} + +func (_c *shirleyTempleGrenadineCall) Panic(msg string) *shirleyTempleGrenadineCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *shirleyTempleGrenadineCall) Once() *shirleyTempleGrenadineCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *shirleyTempleGrenadineCall) Twice() *shirleyTempleGrenadineCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *shirleyTempleGrenadineCall) Times(i int) *shirleyTempleGrenadineCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *shirleyTempleGrenadineCall) WaitUntil(w <-chan time.Time) *shirleyTempleGrenadineCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *shirleyTempleGrenadineCall) After(d time.Duration) *shirleyTempleGrenadineCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *shirleyTempleGrenadineCall) Run(fn func(args mock.Arguments)) *shirleyTempleGrenadineCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *shirleyTempleGrenadineCall) Maybe() *shirleyTempleGrenadineCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *shirleyTempleGrenadineCall) TypedRun(fn func()) *shirleyTempleGrenadineCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + fn() + }) + return _c +} + +func (_c *shirleyTempleGrenadineCall) OnGetCherry() *shirleyTempleGetCherryCall { + return _c.Parent.OnGetCherry() +} + +func (_c *shirleyTempleGrenadineCall) OnGrenadine() *shirleyTempleGrenadineCall { + return _c.Parent.OnGrenadine() +} + +func (_c *shirleyTempleGrenadineCall) Onale(ginger string) *shirleyTemplealeCall { + return _c.Parent.Onale(ginger) +} + +func (_c *shirleyTempleGrenadineCall) OnGetCherryRaw() *shirleyTempleGetCherryCall { + return _c.Parent.OnGetCherryRaw() +} + +func (_c *shirleyTempleGrenadineCall) OnGrenadineRaw() *shirleyTempleGrenadineCall { + return _c.Parent.OnGrenadineRaw() +} + +func (_c *shirleyTempleGrenadineCall) OnaleRaw(ginger interface{}) *shirleyTemplealeCall { + return _c.Parent.OnaleRaw(ginger) +} + +func (_m *shirleyTempleMock) ale(ginger string) { + _m.Called(ginger) +} + +func (_m *shirleyTempleMock) Onale(ginger string) *shirleyTemplealeCall { + return &shirleyTemplealeCall{Call: _m.Mock.On("ale", ginger), Parent: _m} +} + +func (_m *shirleyTempleMock) OnaleRaw(ginger interface{}) *shirleyTemplealeCall { + return &shirleyTemplealeCall{Call: _m.Mock.On("ale", ginger), Parent: _m} +} + +type shirleyTemplealeCall struct { + *mock.Call + Parent *shirleyTempleMock +} + +func (_c *shirleyTemplealeCall) Panic(msg string) *shirleyTemplealeCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *shirleyTemplealeCall) Once() *shirleyTemplealeCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *shirleyTemplealeCall) Twice() *shirleyTemplealeCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *shirleyTemplealeCall) Times(i int) *shirleyTemplealeCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *shirleyTemplealeCall) WaitUntil(w <-chan time.Time) *shirleyTemplealeCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *shirleyTemplealeCall) After(d time.Duration) *shirleyTemplealeCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *shirleyTemplealeCall) Run(fn func(args mock.Arguments)) *shirleyTemplealeCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *shirleyTemplealeCall) Maybe() *shirleyTemplealeCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *shirleyTemplealeCall) TypedRun(fn func(string)) *shirleyTemplealeCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + _ginger := args.String(0) + fn(_ginger) + }) + return _c +} + +func (_c *shirleyTemplealeCall) OnGetCherry() *shirleyTempleGetCherryCall { + return _c.Parent.OnGetCherry() +} + +func (_c *shirleyTemplealeCall) OnGrenadine() *shirleyTempleGrenadineCall { + return _c.Parent.OnGrenadine() +} + +func (_c *shirleyTemplealeCall) Onale(ginger string) *shirleyTemplealeCall { + return _c.Parent.Onale(ginger) +} + +func (_c *shirleyTemplealeCall) OnGetCherryRaw() *shirleyTempleGetCherryCall { + return _c.Parent.OnGetCherryRaw() +} + +func (_c *shirleyTemplealeCall) OnGrenadineRaw() *shirleyTempleGrenadineCall { + return _c.Parent.OnGrenadineRaw() +} + +func (_c *shirleyTemplealeCall) OnaleRaw(ginger interface{}) *shirleyTemplealeCall { + return _c.Parent.OnaleRaw(ginger) +} diff --git a/testdata/source/a/mock_usage_test.go b/testdata/source/a/mock_usage_test.go new file mode 100644 index 0000000..3f3d201 --- /dev/null +++ b/testdata/source/a/mock_usage_test.go @@ -0,0 +1,27 @@ +package a + +import ( + "testing" +) + +func TestGeneratedMocks(t *testing.T) { + var piniaColadaMock PiniaColada = newPiniaColadaMock(t). + OnRhum().TypedReturns("rum").Once(). + OnPine("test.txt").Once(). + OnCoconut().Once(). + Parent + + piniaColadaMock.Rhum() + piniaColadaMock.Pine("test.txt") + piniaColadaMock.Coconut() + + var shirleyTempleMock shirleyTemple = newShirleyTempleMock(t). + Onale("test.txt").Once(). + OnGrenadine().Once(). + OnGetCherry().TypedReturns("maraschino").Once(). + Parent + + shirleyTempleMock.ale("test.txt") + shirleyTempleMock.Grenadine() + shirleyTempleMock.GetCherry() +} diff --git a/testdata/source/b/go.mod b/testdata/source/b/go.mod new file mode 100644 index 0000000..68e91a6 --- /dev/null +++ b/testdata/source/b/go.mod @@ -0,0 +1,16 @@ +module b + +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 +) diff --git a/testdata/source/b/go.sum b/testdata/source/b/go.sum new file mode 100644 index 0000000..0c98ef7 --- /dev/null +++ b/testdata/source/b/go.sum @@ -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= diff --git a/testdata/source/b/interfaces.go b/testdata/source/b/interfaces.go new file mode 100644 index 0000000..be80605 --- /dev/null +++ b/testdata/source/b/interfaces.go @@ -0,0 +1,9 @@ +package b + +import "context" + +type PiniaColada interface { + Rhum(ctx context.Context) string + Pine(apple string) + Coconut() +} diff --git a/testdata/source/b/mock_gen.go.golden b/testdata/source/b/mock_gen.go.golden new file mode 100644 index 0000000..58c2f39 --- /dev/null +++ b/testdata/source/b/mock_gen.go.golden @@ -0,0 +1,309 @@ +// Code generated by mocktail; DO NOT EDIT. + +package b + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/mock" +) + +// piniaColadaMock mock of PiniaColada. +type piniaColadaMock struct{ mock.Mock } + +// NewPiniaColadaMock creates a new piniaColadaMock. +func NewPiniaColadaMock(tb testing.TB) *piniaColadaMock { + tb.Helper() + + m := &piniaColadaMock{} + m.Mock.Test(tb) + + tb.Cleanup(func() { m.AssertExpectations(tb) }) + + return m +} + +func (_m *piniaColadaMock) Coconut() { + _m.Called() +} + +func (_m *piniaColadaMock) OnCoconut() *piniaColadaCoconutCall { + return &piniaColadaCoconutCall{Call: _m.Mock.On("Coconut"), Parent: _m} +} + +func (_m *piniaColadaMock) OnCoconutRaw() *piniaColadaCoconutCall { + return &piniaColadaCoconutCall{Call: _m.Mock.On("Coconut"), Parent: _m} +} + +type piniaColadaCoconutCall struct { + *mock.Call + Parent *piniaColadaMock +} + +func (_c *piniaColadaCoconutCall) Panic(msg string) *piniaColadaCoconutCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *piniaColadaCoconutCall) Once() *piniaColadaCoconutCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *piniaColadaCoconutCall) Twice() *piniaColadaCoconutCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *piniaColadaCoconutCall) Times(i int) *piniaColadaCoconutCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *piniaColadaCoconutCall) WaitUntil(w <-chan time.Time) *piniaColadaCoconutCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *piniaColadaCoconutCall) After(d time.Duration) *piniaColadaCoconutCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *piniaColadaCoconutCall) Run(fn func(args mock.Arguments)) *piniaColadaCoconutCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *piniaColadaCoconutCall) Maybe() *piniaColadaCoconutCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *piniaColadaCoconutCall) TypedRun(fn func()) *piniaColadaCoconutCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + fn() + }) + return _c +} + +func (_c *piniaColadaCoconutCall) OnCoconut() *piniaColadaCoconutCall { + return _c.Parent.OnCoconut() +} + +func (_c *piniaColadaCoconutCall) OnPine(apple string) *piniaColadaPineCall { + return _c.Parent.OnPine(apple) +} + +func (_c *piniaColadaCoconutCall) OnRhum() *piniaColadaRhumCall { + return _c.Parent.OnRhum() +} + +func (_c *piniaColadaCoconutCall) OnCoconutRaw() *piniaColadaCoconutCall { + return _c.Parent.OnCoconutRaw() +} + +func (_c *piniaColadaCoconutCall) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return _c.Parent.OnPineRaw(apple) +} + +func (_c *piniaColadaCoconutCall) OnRhumRaw() *piniaColadaRhumCall { + return _c.Parent.OnRhumRaw() +} + +func (_m *piniaColadaMock) Pine(apple string) { + _m.Called(apple) +} + +func (_m *piniaColadaMock) OnPine(apple string) *piniaColadaPineCall { + return &piniaColadaPineCall{Call: _m.Mock.On("Pine", apple), Parent: _m} +} + +func (_m *piniaColadaMock) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return &piniaColadaPineCall{Call: _m.Mock.On("Pine", apple), Parent: _m} +} + +type piniaColadaPineCall struct { + *mock.Call + Parent *piniaColadaMock +} + +func (_c *piniaColadaPineCall) Panic(msg string) *piniaColadaPineCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *piniaColadaPineCall) Once() *piniaColadaPineCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *piniaColadaPineCall) Twice() *piniaColadaPineCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *piniaColadaPineCall) Times(i int) *piniaColadaPineCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *piniaColadaPineCall) WaitUntil(w <-chan time.Time) *piniaColadaPineCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *piniaColadaPineCall) After(d time.Duration) *piniaColadaPineCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *piniaColadaPineCall) Run(fn func(args mock.Arguments)) *piniaColadaPineCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *piniaColadaPineCall) Maybe() *piniaColadaPineCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *piniaColadaPineCall) TypedRun(fn func(string)) *piniaColadaPineCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + _apple := args.String(0) + fn(_apple) + }) + return _c +} + +func (_c *piniaColadaPineCall) OnCoconut() *piniaColadaCoconutCall { + return _c.Parent.OnCoconut() +} + +func (_c *piniaColadaPineCall) OnPine(apple string) *piniaColadaPineCall { + return _c.Parent.OnPine(apple) +} + +func (_c *piniaColadaPineCall) OnRhum() *piniaColadaRhumCall { + return _c.Parent.OnRhum() +} + +func (_c *piniaColadaPineCall) OnCoconutRaw() *piniaColadaCoconutCall { + return _c.Parent.OnCoconutRaw() +} + +func (_c *piniaColadaPineCall) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return _c.Parent.OnPineRaw(apple) +} + +func (_c *piniaColadaPineCall) OnRhumRaw() *piniaColadaRhumCall { + return _c.Parent.OnRhumRaw() +} + +func (_m *piniaColadaMock) Rhum(_ context.Context) string { + _ret := _m.Called() + + if _rf, ok := _ret.Get(0).(func() string); ok { + return _rf() + } + + _ra0 := _ret.String(0) + + return _ra0 +} + +func (_m *piniaColadaMock) OnRhum() *piniaColadaRhumCall { + return &piniaColadaRhumCall{Call: _m.Mock.On("Rhum"), Parent: _m} +} + +func (_m *piniaColadaMock) OnRhumRaw() *piniaColadaRhumCall { + return &piniaColadaRhumCall{Call: _m.Mock.On("Rhum"), Parent: _m} +} + +type piniaColadaRhumCall struct { + *mock.Call + Parent *piniaColadaMock +} + +func (_c *piniaColadaRhumCall) Panic(msg string) *piniaColadaRhumCall { + _c.Call = _c.Call.Panic(msg) + return _c +} + +func (_c *piniaColadaRhumCall) Once() *piniaColadaRhumCall { + _c.Call = _c.Call.Once() + return _c +} + +func (_c *piniaColadaRhumCall) Twice() *piniaColadaRhumCall { + _c.Call = _c.Call.Twice() + return _c +} + +func (_c *piniaColadaRhumCall) Times(i int) *piniaColadaRhumCall { + _c.Call = _c.Call.Times(i) + return _c +} + +func (_c *piniaColadaRhumCall) WaitUntil(w <-chan time.Time) *piniaColadaRhumCall { + _c.Call = _c.Call.WaitUntil(w) + return _c +} + +func (_c *piniaColadaRhumCall) After(d time.Duration) *piniaColadaRhumCall { + _c.Call = _c.Call.After(d) + return _c +} + +func (_c *piniaColadaRhumCall) Run(fn func(args mock.Arguments)) *piniaColadaRhumCall { + _c.Call = _c.Call.Run(fn) + return _c +} + +func (_c *piniaColadaRhumCall) Maybe() *piniaColadaRhumCall { + _c.Call = _c.Call.Maybe() + return _c +} + +func (_c *piniaColadaRhumCall) TypedReturns(a string) *piniaColadaRhumCall { + _c.Call = _c.Return(a) + return _c +} + +func (_c *piniaColadaRhumCall) ReturnsFn(fn func() string) *piniaColadaRhumCall { + _c.Call = _c.Return(fn) + return _c +} + +func (_c *piniaColadaRhumCall) TypedRun(fn func()) *piniaColadaRhumCall { + _c.Call = _c.Call.Run(func(args mock.Arguments) { + fn() + }) + return _c +} + +func (_c *piniaColadaRhumCall) OnCoconut() *piniaColadaCoconutCall { + return _c.Parent.OnCoconut() +} + +func (_c *piniaColadaRhumCall) OnPine(apple string) *piniaColadaPineCall { + return _c.Parent.OnPine(apple) +} + +func (_c *piniaColadaRhumCall) OnRhum() *piniaColadaRhumCall { + return _c.Parent.OnRhum() +} + +func (_c *piniaColadaRhumCall) OnCoconutRaw() *piniaColadaCoconutCall { + return _c.Parent.OnCoconutRaw() +} + +func (_c *piniaColadaRhumCall) OnPineRaw(apple interface{}) *piniaColadaPineCall { + return _c.Parent.OnPineRaw(apple) +} + +func (_c *piniaColadaRhumCall) OnRhumRaw() *piniaColadaRhumCall { + return _c.Parent.OnRhumRaw() +} diff --git a/testdata/source/b/mock_usage_test.go b/testdata/source/b/mock_usage_test.go new file mode 100644 index 0000000..303db98 --- /dev/null +++ b/testdata/source/b/mock_usage_test.go @@ -0,0 +1,18 @@ +package b + +import ( + "context" + "testing" +) + +func TestGeneratedMocks(t *testing.T) { + piniaColadaMock := NewPiniaColadaMock(t). + OnRhum().TypedReturns("rum").Once(). + OnPine("test.txt").Once(). + OnCoconut().Once(). + Parent + + piniaColadaMock.Rhum(context.Background()) + piniaColadaMock.Pine("test.txt") + piniaColadaMock.Coconut() +} diff --git a/testdata/src/a/a.go b/testdata/src/a/a.go index 6637fff..37ad2d0 100644 --- a/testdata/src/a/a.go +++ b/testdata/src/a/a.go @@ -42,4 +42,4 @@ type Strawberry interface { type Orange interface { Juice() <-chan struct{} -} +} \ No newline at end of file