Hacker News new | ask | show | jobs
by tuxie_ 1810 days ago
I'm sorry, I did not intend to offend anyone obviously. Needless to say, this is just my opinion condensed in a sentence (therefore lacking a lot of context, which I should have provided).

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.

3 comments

by claiming when something stops being a unit test, you have to define what a unit test is. Now, I do think there is a good, reasonable definition of a unit test and it's looser than yours. A single function that reaches out for an API call via another function and does N other steps of compute that has the API call mocked is still a unit test.

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..

this convo has made me realize that our terms for testing do not pair well with actual testing practices, which i find easier to conceptualize in terms of "coarseness" relative to fundamental units of work in a system as opposed to this binary notion of unit versus integration.

i might write a blog post about this!

More and more I'm seeing "unit testing" becoming the generic term for what we used to just call plain old testing. A lot of companies had never had anything remotely close to unit testing but called all their automated tests unit tests, at least in part out of ignorance of the difference. My current company has gone a step further and calls their extremely manual and poorly defined QA test plans unit testing.

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.

So components that talk to the outside can't be unit-tested at all?
Hi detaro. Good question. If all my module does is make an api call, and I mock the API, what am I testing? I would rather leave that out of the unit tests because the added value is, in my opinion, close to none if you are relying on mocked data.

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.

Ok, then go one level in: If a component uses the "only makes an API call module", how do I unit test it? I can't let it use the module to make the API call (because the API might not be available in testing/that's an integration test/...), and I can't mock it, because using a mock would make it a not-unit test? I guess this gets at the line between mocks and stubs, but I never found that all that convincing.
Yes, you just don't unit test it, because if you mock out the only dependency it has you are left with nothing. So you are not unit testing anything anyway. You know what I mean? That code can (and should) be tested, through an integration test.