6 ms·
Do you have any examples of where mocking has let you down? I found creating unit tests with mocks and DI extremely easy and satisfying. At least for me, they a
by uw_rob 10y ago
Do you have any examples of where mocking has let you down? I found creating unit tests with mocks and DI extremely easy and satisfying. At least for me, they also provide a pretty convincing argument that the tested code is correct.
Also, they are basically required if you want to do any testing with external services. I'm not sure how else you could create unit tests for DBs etc.
- brianwawok 10y agoYes. Every project I have ever used with a web of mocks, especially around final things made refactoring near impossible. At some point the codebase got so brittle, it fell apart. I find it funny that in most discussions around mocking, a database is the given example. 100% of the time when I need a database for "unit tests", I use a database. Not a mock. I don't want to know that when I do select blar from flar I get back the value 7, and hardcode it. I want to actually load the data and see it happen. Because if I don't, how do I know that my code will actually work in production? Sometimes that involves sqllite (easy but not preferred because I don't use it in production). Sometimes it just involves running a local database that gets built up for a unit test run. Sometimes something like docker, sometimes not. Sometimes a shared "dev" database. Lots of options. But literally every project I have been involved with that used a REAL database instead of mocking it out, has worked better and been more stable and easier to change. Now for actual external services.. say you call some Netflix API. Yes don't call that for real in a unit test. But you can do that with either: a) Basic mocking, because you created a very simple API. You don't just call some random driver directly with your code, right? You have an interface in front of it. Then you can mock it with no final or static override crap going on. b) If your API is clean enough, you can just code up a very simple dummy implementation. Lets you set the return value for methods, then the next call it gives them back. I don't feel that strongly between A and B above. But I feel very very very strongly about people mocking databases or, even worse, every random call between classes in their own codebase, or someone elses codebase.
- wlamartin 10y ago> I want to actually load the data and see it happen. Because if I don't, how do I know that my code will actually work in production? This would fall under the purview of integration/acceptance testing?
- brianwawok 10y agoI don't really want to split hairs about what test is what test. I do not write a test that would involve mocking a database. If I have 1 test, it is going to be 1 test that uses the database. Its "the test".. not a "unit test" or an "acceptance test" or a "integration test".. just, "the test."
- softawre 10y agoMy goal is to be pragmatic with testing. We have "tests" that actually spin up a real database too, but not all of our tests do that. Where I'm with you is fighting the "architects". The guys that will constantly say you're not doing "real unit testing" and that you should mock every function (and then have to change every mock with every change and blah blah). To me, being pragmatic with testing is a key component of GTD in modern software development.
- ng12 10y agoAre you working with other developers on these projects? "The test" failing is much less useful information than a "unit test" failing. If the unit test fails I know it's something pretty fundamental -- I can isolate it to a single method. If the integration test fails, but the unit test passed, I can be reasonably assured the problem is with the database. Tests are just as much about making software maintainable as they are about making sure it's correct.
- brianwawok 10y agoYes, these were for fortune 2000 companies or late state startups... projects with piles of "unit tests" where you try to test one class at a time and hand type what a database does were all inevitably crap, and either failed and got rewritten, or all the crap got written out.
- ng12 10y ago> I find it funny that in most discussions around mocking, a database is the given example. 100% of the time when I need a database for "unit tests", I use a database. Not a mock. I don't want to know that when I do select blar from flar I get back the value 7, and hardcode it. I want to actually load the data and see it happen. Because if I don't, how do I know that my code will actually work in production? That is not a unit test. What if your database is corrupted? What if your mock Netflix API is buggy? The second you do anything like that you're no longer unit testing. The whole point is you're testing a single method/class in isolation -- Mockito gives you the power to assume external structures (the database) work as expected. If you don't like unit testing, sure. But unit testing is what Mockito is all about.
- brianwawok 10y agoWhat if my DB is corrupted - Why did it get corrupted? Sounds like you have a good failure to chase down. It would be even worse if your prod DB got corrupt! For most use cases, a given piece needs 1 test around it. "The test". If you can test your logic + view + db all in 1 test, you get a pretty huge efficiency gain.. over sitting there writing "unit tests" where you mock what a select * from a database returns. Life is too short to do that.
- ng12 10y agoI'm just pointing out that your problem is with unit tests, not with Mockito. I think unit tests are invaluable on large projects, so I find Mockito to be an incredibly valuable tool. I'm also not arguing against integration testing, just that unit testing is not the time to worry about your prod environment.
- brianwawok 10y agoWhy should your tools having to spin up a database in 3 seconds conflate local dev testing and your prod environment? Not advocating a 8 database cluster with hot failover on your laptop.. just a simple database.
- uw_rob 10y ago
- whoisthemachine 10y agoIt sounds like you are not testing units of work with your unit tests that require "webs of mocks", but rather higher level integration tests. Unit tests should be testing code that has a small set of dependencies and test a single operation with those dependencies.