-
Notifications
You must be signed in to change notification settings - Fork 76
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
Should we support mocking modules without behaviour? #9
Comments
Yeah, in my opinion it breaks the explicit contract mantra which comes with all the issues mentioned in the article. A mock exists to replace external dependencies in your code and how are you going to replace it if you don't even have a contract? If we want to have this functionality, I would put it under a very explicit and long name, since it is not a pattern I think we should promote. Something like:
|
Cool. I'm ok with closing this for now. Maybe if demand for it becomes obvious, we can come back? |
Sounds great. I am fine if we keep this open though because I am sure other will ask about it too. |
For what it is worth, the requirement of an explicit contract is the reason that I'm bringing this package into our team's codebase. There are plenty of other tools out there that allow us to get around it. I'm glad the goal is to keep this requiring the behaviour. |
What would be the "correct" solution to mock external libraries that doesn't have behaviorus? Create an internal wrapper that delegates function calls to the external library and use that as behaviour? UPDATE: Right now for example I just did a wrapper like this for ExTwitter
declaring only the functions I use |
@alex88 what the library defines is irrelevant to your application. Your application needs to decide on what it depends on. If it is the same API as the TwitterClient project, then good for you. :) |
Hey @josevalim! First of all, thank you for the great work with this library! ❤️ I've read your blog post on this subject and I've been trying to follow it when writing my applications. In the modules of our own application, we can define the behaviors and then use For instance, I use the ExStatsD library. Currently, I have a Thank you for your input 🙌 |
Yes, you define what API your application expects in terms of stats and that is your behaviour. |
@josevalim after some months of experience using this library, I'd like to raise a new question on this issue: should Mox also accept function specs (i.e. If I want to have a mock for a certain module in my app (because it does some heavy computations, for instance) and want to use Moreover, there are some modules from the standard library that provide What are your thoughts on this? |
Specs and functions are equivalent, so the same thought process that applies to functions should also apply to specs. Mox wants you to define meaningful contracts, instead of mechanical ones. You talk about |
Yeah, callbacks and specs aren't the same, but for the purpose of ensuring that the mock and the real implementation don't drift away, they both fulfill it, right? In what sense do you call this a "mechanical contract"? I agree that a contract through a Behaviour is more explicit, and I usually apply it when dealing with 3rd parties. However, it seems overkill to do it for the standard lib of a language. How would you actually employ this? Have a module like What do you think of the possibility of the |
Adding I think one important thing to consider is this: do you want to mock your interaction with the file system, even if you can actually use the file system in your tests? If you do, then having a clear interface on it is a benefit since you are considering it an external part of your system and setting a boundary on it in my opinion. Another thing to consider: if you mock the I might have reiterated something that José already said, but maybe putting it a different way can help see it in a clearer way :). |
@dcaixinha to reinforce @whatyouhide arguments, you don't want to depend on the mechanical contracts based on the File and Enum APIs. You most likely want to define a contract that depends on your domain. Let's take a quick example, consuming the twitter API. The API you are going to mock is not |
Hey guys, sorry for resurrecting this issue after so much time, but I have some further thoughts to debate with you. First of all, thank you for your feedback 🙌 I agree with most of your points (e.g. the importance of defining explicit contracts, avoid leaking implementation details), but there are some points I'm not sure I agree.
This is a highly subjective topic and indeed I could just use the file system in the tests. Elixir has made me reconsider in several ways what a pure unit test is (for instance, we might not want to create mocks for every collaborator, especially if they're just running pure functions), there are still some cases I think mocks should be used, particularly when testing for side effects. My example above was not thoroughly explained, but imagine that you're doing a
I completely agree with that example, but how would you translate it to a testing using @josevalim from your example, we would create a mock for |
You test it directly and in isolation. Usually behind some flag such as |
Hey peeps, I am wondering how you deal with having to create a module that defines a behavior with My concern is that I end up with many tiny modules doing that all over the place because my dependency is technically a function. Still, I have some limitations around it and/or want to take advantage of So I am wondering how you are dealing with mocking in your codebase and for such sitation. |
From your description, it may be that:
Other than that, If you have only one callback, then you have to define a behaviour, because it needs to be a explicit contract of your code. We discuss all of this in: https://dashbit.co/blog/mocks-and-explicit-contracts I will close this for now, because I think those discussions are likely better moved to ElixirForum from now on. :) |
It's possible to verify function name and arity without behaviour callbacks. I built support for this in double, but I'm curious if there are good reasons not to support this. Does it break the "explicit contract" mantra?
Related discussion: http://teamon.eu/2017/different-approach-to-elixir-mocks-doubles/#comment-3542001464
The text was updated successfully, but these errors were encountered: