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

How to match error with boolean function? #425

Closed
kaoet opened this issue Mar 11, 2021 · 7 comments · Fixed by #437
Closed

How to match error with boolean function? #425

kaoet opened this issue Mar 11, 2021 · 7 comments · Fixed by #437

Comments

@kaoet
Copy link
Contributor

kaoet commented Mar 11, 2021

I want to test whether my err is "not exist", I found os.IsNotExist() in the standard library. How can I use it in my tests? I'm wondering something like

Expect(err).To(MatchError(os.IsNotExist))

But that doesn't work.

@blgm
Copy link
Collaborator

blgm commented Mar 11, 2021

Expect(err).NotTo(HaveOccurred())

Does this help?

@onsi
Copy link
Owner

onsi commented Mar 11, 2021

or if you want to assert the exact error you can:

Expect(err).To(MatchError(os.ErrNotExist))

that's the actual error. os.IsNotExist() is a function - if you wanted to use it you would:

Expect(os.IsNotExist(err)).To(BeTrue())

@kaoet
Copy link
Contributor Author

kaoet commented Mar 12, 2021

@onsi Thanks for helping.
Actually, I over simplified my use case. I was just taking os.IsNotExist() as an example.

My original use case is that, I have a library, which returns library specific error and provides IsXXXError() functions just like os.IsNotExist(). But that library doesn't provide a convient way to construct an error of specific type like os.ErrNotExist.

What I want to test is wheter my error is nil or is some error matching IsXXXError(). I want to write something like:

Expect(err).To(Or(BeNil(), MatchError(IsXXXError)))

As you can see, since I want to use it inside Or(), I must convert IsXXXError into a matcher.

I think those IsXXXError() functions, which have signature func(error)bool is a common pattern in Go. Can we support those functions as parameter of MatchError()?

Moreover, can we have a quick way to convert arbitrary func(...)bool to matchers rather than having to write an implementation of GomegaMatcher interface?


My current workaround is to use an if statement like:

if err := DoSomething(); err != nil {
  Expect(IsXXXError(err)).To(BeTrue())
}

But it's long and doesn't give me useful error message when it fails. Gomega just says "false is not true".

@onsi
Copy link
Owner

onsi commented Mar 12, 2021

hey @kaoet I think your best bet here is to make one custom matcher that takes a func(...) bool as an argument and handles your use case.

Something like: BeNilOrSatisfy(f func(...) bool{}). You could then write tests like:

Expect(err).To(BeNilOrSatisfy(os.IsNotExist))

I imagine such a matcher would not be too hard to write - but let me know if you'd like some help with it.

@blgm
Copy link
Collaborator

blgm commented Mar 12, 2021

A helper function is another approach:

err := DoSomething()
checkError(err)
func checkError(err error) {
  switch err.(type) {
    case nil, OtherAcceptableErrorType:
      return
    default:
      ExpectWithOffset(1, err).NotTo(HaveOccurred(), "extra message can be added here")
    }
  }
}

@blgm
Copy link
Collaborator

blgm commented Apr 23, 2021

Hi @kaoet. Have the responses above been helpful?

@kaoet
Copy link
Contributor Author

kaoet commented Apr 25, 2021

@blgm No, finally we implemented a MatchErrorFn() matcher in our own project, because it's so commonly used.

I'm always thinking MatchError() function in Gomega should support pass in a func (error) bool function as parameter in addition to string and error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants