Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support directory exclusion when generating mocks #458

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Table of Contents
- [Expecter Interfaces](#expecter-interfaces)
- [Mock constructors](#mock-constructors)
- [Extended Flag Descriptions](#extended-flag-descriptions)
- [Excluding Directories](#excluding-directories)
- [Mocking interfaces in `main`](#mocking-interfaces-in-main)
- [Configuration](#configuration)
* [Example](#example)
Expand Down Expand Up @@ -367,6 +368,11 @@ The following descriptions provide additional elaboration on a few common parame
| `--exported` | Use `mockery --exported` to generate public mocks for private interfaces. |
| `--with-expecter` | Use `mockery --with-expecter` to generate `EXPECT()` methods for your mocks. This is the preferred way to setup your mocks. |

Excluding Directories
---------------------

Directories can be excluded from mock generation by placing a file `.mockery_skip` inside them. Mocks will not be generated for any types present in a directory containing such a file nor for any in its sub-directories.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, let's call this .mockery_skip_all. I envision we might want a .mockery_skip that skips just a single directory, whereas the _all can skip the entire tree.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By "skip the entire tree" vs "just a single directory" is the intended meaning that

  • "skip the entire tree" is recursively down the tree from this point
  • "just a single directory" is don't generate mocks for files in this directory but do for those in directories beneath this one
    ? (checking I've got that right in my head)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep that sounds right, I feel like we might want both options at some point but we can just focus on "skip the entire tree" as you were originally doing. Thanks!


Mocking interfaces in `main`
----------------------------

Expand Down
13 changes: 13 additions & 0 deletions pkg/walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ func (w *Walker) doWalk(ctx context.Context, p *Parser, dir string, visitor Walk

files, err := ioutil.ReadDir(dir)
if err != nil {
log.Err(err).Msgf("Error reading directory")
return
}

OUTER:
for _, file := range files {
if strings.HasPrefix(file.Name(), ".") || strings.HasPrefix(file.Name(), "_") {
continue
Expand All @@ -80,6 +82,17 @@ func (w *Walker) doWalk(ctx context.Context, p *Parser, dir string, visitor Walk

if file.IsDir() {
if w.Recursive {
nextFiles, err := ioutil.ReadDir(path)
if err != nil {
log.Err(err).Msgf("Error reading directory")
return
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the doWalk function doesn't provide a way to bubble the error up, I feel like this should be a fatal error. But, we really should fix doWalk not returning errors.

}
for _, nextFile := range nextFiles {
if nextFile.Name() == ".mockery_skip" {
continue OUTER
Copy link
Collaborator

@LandonTClipp LandonTClipp May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to really avoid labels if at all possible. Actually, I think we can stat for .mockery_skip at the top of doWalk and simply return if it exists.

Shameless plug but you might want to look into https://pkg.go.dev/github.com/chigopher/pathlib and then you can just do pathlib.Path(dir).Join(".mockery_skip").Exists() to check.

}
}

generated = w.doWalk(ctx, p, path, visitor) || generated
if generated && w.LimitOne {
return
Expand Down
27 changes: 27 additions & 0 deletions pkg/walker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,30 @@ func TestPackagePrefix(t *testing.T) {
w.Walk(context.Background(), gv)
assert.Regexp(t, regexp.MustCompile("package prefix_test_test"), bufferedProvider.String())
}

func TestWalkerDirectorySkip(t *testing.T) {
if testing.Short() {
t.Skip("skipping recursive walker test")
}

wd, err := os.Getwd()
assert.NoError(t, err)
w := Walker{
BaseDir: wd,
Recursive: true,
LimitOne: false,
Filter: regexp.MustCompile(".*"),
}

gv := NewGatheringVisitor()

// Generating mocks, ignoring the fixtures directory
skipMarker, err := os.Create(getFixturePath(".mockery_skip"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use pathlib for this.

assert.NoError(t, err)
defer func() { os.Remove(skipMarker.Name()) }()

w.Walk(context.Background(), gv)

// There are 4 mocks generated from the files within pkg/* but outside pkg/fixtures/*
assert.Len(t, gv.Interfaces, 4)
}