Those points of contact with 3rd parties should be clearly defined and encapsulated at the perimeter of your system. Mock at that level. Not when testing business logic.
Those points of contact with 3rd parties should be clearly defined and encapsulated at the perimeter of your system. Mock at that level. Not when testing business logic.
sometimes the dependency is not a third party, but it may be code that requires a ton of setup (as mentioned in article) that's not worth the cost. it may make sense to just mock at that point to actually test the rest of the business logic in a function. I don't think i'd say "well, that's no longer a unit test!". You can argue that it's a more brittle test, sure.
update: also, i'll be honest that comments like this really rub me the wrong way. This type of dogmatism around what is or isn't unit testing (which is a pretty ill-defined phrase in industry) is something that needs to stop. I think it hurts new practioners in the field who are mislead into black and white thinking.
I was not aiming to define what a unit test is, more like when it stops being a unit test (which I thought it would be an easier agreement to reach than a definition of what is, but I guess I underestimated the task).
My point was that if you have to mock, for example, a DB call inside your business logic, well you are writing an integration test at that point, whether or not you mock the DB out. If you design your code so that you only have those dependencies at the edge of the system then you get, in my opinion, a much cleaner design and much more testable code.
Too much mocking (and/or more like mocking in the wrong places) is a code smell in my opinion.
Now, if the module does more than just call the API then I would argue that it's breaking the single responsibility principle and would prefer to split it into a module that does only the call and another that does the rest.
can it be a smell? maybe, that depends. Does it break your idea of single responsibility? maybe. Is it an integration test? not ... really because the test is primarily designed to verify the behavior of the rules of the function and not its interaction with a third party system.
so while you can argue that mocking is a smell in that context, that doesn't change the fact that it's still a unit test!
all that said, one can still make a case that the fundamental unit of work for a given context is not really a function, and so testing functions are actually integration tests! so I'll also grant that these definitions can be very context sensitive..
i might write a blog post about this!
As for my 2 cents, I find single assert principle helpful as it helps narrow down the unit of behavior your actually testing. I don't care if a test covers a single function or half the code base, as long as it's clear why it is specifically testing for and what has gone wrong if it fails.
Does it mean:
- A test of some of the requirements that can be done very fast. (That's my preferred form when involves a large part of the code)
- A test of a small piece of code that makes a lot of assumptions about other code by mocking it. (Not a good idea, but it might work in your organization)
P.S. I did not read your post, while I was writing mine.
So you can also mock your encapsulation in the next layer, than that one in the next, etc
Never let someone tell you what unit tests are.
Sorry, I would like to answer your comment since it seems that it upset you, and nothing was further from my intention. But I honestly don't understand what you mean.
I was not aiming to define what a unit test is, more like when it stops being a unit test, and I think that if you have to mock, for example, a DB call inside your business logic, well you are writing an integration test at that point, whether or not you mock the DB out. If you design your code so that you only have those dependencies at the edge of the system then you get, in my opinion, a much cleaner design and much more testable code.