3 ms·
This is straight-up bad advice. You don't test the http.Client as part of your business logic, even (especially) if your business logic makes HTTP requests. In
by sagichmal 9y ago
This is straight-up bad advice.
You don't test the http.Client as part of your business logic, even (especially) if your business logic makes HTTP requests. Instead, you trust that package http is already well-tested, mock out http.Client as an abstract HTTP Request Do-er, and you downscope your tests to your business logic exclusively.
- sdhgaiojfsa 9y agoLots of people have different opinions on this. You're entitled to yours, but I think it's hasty to call it bad advice. I'm not so worried about http.Client behaving incorrectly, but I am worried about the server I'm targeting behaving in a way that's different than my expectations. I'm also worried about getting cookie, post-data, url, etc. formats wrong. Even if they match what I put in my mock, they won't necessarily match what's out there in production. I'm worried that I'll handle download resumption wrong, for example. If I have the capability to bring up the target server locally, that's what I will do. If I can't, but it's straightforward to create a work-alike, I'll bring that up in process. Only in the most dire of circumstances will I use mocks to test my code. Think about it this way. What harm is done by using the real object, under the circumstances I described? Sure, if the dependency code breaks, my tests will too. Is that bad? Is there any point in my tests passing when my code won't actually work in production? OK, so maybe the tests will run slower? This matters in the limit, but often times you can use the production dependency without materially increasing test time. OK but what about the CI system using more resources? That will only be a problem of significant economic import if you're running at a scale like Google or Facebook. My opinion is there are a few main valid objections to my approach. One is an argument about the size of the test code. In some cases, bringing up the production dependency will require more code than a mock. Sometimes a lot more code. My response is that we should make it easier to bring up the production dependency! But if we can't, I can see the case for a mock or a fake. The other counterargument is for when we really are interested in testing the sequence of interactions the code under test has with the production system. In that event, I guess I'm ok with using a mock, but I think most of the time we're more interested in testing state. We can also use things like testvalue injection to test behavior sequences, which is normally a lighter-weight approach, and in some cases can allow you to reproduce paths that you'd otherwise have trouble hitting, even with a mock.
- sifoo 9y agoThis is how I do it as well these days, testing as much of the final product as possible in the normal test run. It's not that I didn't try unit testing and mocking, or don't understand; my experience tells me that it's not a constructive approach. This means that I always test mostly the same code that other people run, which prevents all sorts of mistakes; and I don't waste precious time writing and maintaining mocks. It will creep up on you, but if you keep mocking everything, sooner or later the effort required to change anything will start hurting the project. It's easy to loose track of the goal; which should be preventing as many production errors as possible as effectively as possible, not checking all the boxes of whatever religion.
- sagichmal 9y ago> I am worried about the server I'm targeting behaving in a way that's different than my expectations This is the responsibility of system or integration tests, not unit tests. (Unit tests are what's under discussion in the article.) > What harm is done by using the real object, under the circumstances I described? Time, energy, and effort, all of which inevitably lead to longer (slower) dev/test cycles.
- sdhgaiojfsa 9y ago> Time, energy, and effort My contention is that using real objects normally does not take materially more of any of these, and thus that most code is served best by being tested only by integration and regression tests. Where my contention is untrue, apply your best judgment, of course. :)
- convolvatron 9y agoi wish i could give you 1 thousand points. isolated unit tests can have value in that the bugs they expose are more easily tracked down. full-system testing, with an honest attempt to do fault injection, by definition exposes all the issues you might have in production. if you have a decent test suite you can honestly claim you can expect it to take client code correctly. i don't know how thats true if you've only tested A against some stubbed out version of B that always returns success. integrated testing is harder and requires more framework. its also kinda necessary, and if you only have the resources to do one or the other, the choice seems pretty clear. i also heartily agree with your comment that since we're supposed to have frictionless and scalable deployment. there is no reason not to test this as part of integration testing and also exploit this function to make integration testing easier.