Live data from Hacker News

Don't Use Mocks

joeblu.com

81–85 of 85 posts

Re: Don't Use Mocks

#81
post #60
post #19

Can we not have articles like this with blanket statements like this please? As with everything in software, no one size fits all. Mocks have their place. There are situations when the only way we can test something out is to mock out a certain function call. Sometimes our dependencies are so complex and deep that we cannot just replace it with a fake. But with a little mock we can replace a function or a class withi…

Sure, the title is clickbait. But the message seemed useful: if your test rigidly requires every call be made in exactly the way it is made now, then your test will be brittle. For a less brittle test, re-implement the functionality in a simpler form. What this article did not do was to describe the trade-off: what you give up by creating a more complicated "fake" (to use the author's term).

A naive question here, should I not then in a unit test, test that an API library is called with specific arguments?

I am confused, wouldn't using simpler and "broader" tests miss test coverage on e.g. specific error handlers?

Re: Don't Use Mocks

#82
post #19

Can we not have articles like this with blanket statements like this please? As with everything in software, no one size fits all. Mocks have their place. There are situations when the only way we can test something out is to mock out a certain function call. Sometimes our dependencies are so complex and deep that we cannot just replace it with a fake. But with a little mock we can replace a function or a class withi…

I don't grasp the difference between a mock and a fake. Both are substitutes for an expensive or unavailable component. Maybe the fake is more dynamic than the mock? The point seems moot.

How I understand it:

A mock is a set of fixed data; sometimes people even load these from YAML documents and the like. They're often re-used for different tests.

A fake is a "fake" object created when needed, with the parameters you need.

Mock:

  user = load_user_mock()
  article = load_article_mock()
  run_test(user, article)
Fake:

  user = newUser(Name: "foo", Email: "foo@example.com")  # Or generate random data
  article = newArticle(User: user, Title: "bar")
  run_test(user, article)
The difference is somewhat subtle, but I often find mocks very inconvenient because you can't "just" change one without lots of stuff falling over. It's also much harder to do something "special" with them for that one test.

Re: Don't Use Mocks

#83

Earlier quoted context omitted.

I don't grasp the difference between a mock and a fake. Both are substitutes for an expensive or unavailable component. Maybe the fake is more dynamic than the mock? The point seems moot.

I actually agree. I think the point the author is trying to make it that fake can be reused in more places and stay relatively same as the code updates. But I personally think that instead of spending the time to write a fake, its better to just spend the time writing actual integration test with the real dependency (eg: just run the db in docker or something) or if you don't want to spend that time, then just record…

If running a micro service use sqlalchemy and switch your db to sqlite for testing purposes.

There are scalability limits to this but for most cases it works extremely well and is fast.

Re: Don't Use Mocks

#84
post #14

Earlier quoted context omitted.

It's all about staying in language though, at least in my opinion. The test suite I don't run is the one that requires the complicated docker compose stack and the local network to look just right. The test suite I do run is the one where I hit "run" in my IDE and then it lets be jump to what failed and debug seconds later. That, IMO, is what mocking is about: making the tests fast and easy to run so they actually ar…

Agree. Mocking is a slippery slope I think. We need to mock, for example, DownstreamAPI01 that our app POSTS to and GETs from, so we can put in accurate and realistic faked responses. We don't strictly need to mock other bits of our own apps - but many people choose to do so. Martin Fowler writes very well about this, and I hadn't even appreciated the "split" between sociable unit tests and solitary tests: https://ma…

95% of unit tests will bring 5% of value and 5% of unit tests will bring 95% of value.

Most unit tests should be handled at the integration level.

Re: Don't Use Mocks

#85
post #5

Nah I'm about done working on rails codebases with 2+ hour CI cycles because developers insist on hammering a database in unit tests.

And I'm done with developers who proudly boast of 95% test coverage using mocked tests because "we don't want to test the database" and then have database changes cause production crashes. "But my tests were all green!" Databases, external APIs, dependency version updates, etc are among the most likely places where unintended changes get introduced. Why would you not test that when catching unintended breaking change…

Get the best of both world by mocking the database API itself. Use the mocks to memoize the db output. Disable the mocks if you need long thorough tests. Determine if the mocks need to be disabled by comparing the date of the last thorough check with the date of the last db schema change. Instead of something global like this, one could come up with something local to the test file, using a system of cassettes. Doing something like this would require to make the database a value and memoize according to its current state, but I think it's doable.
Post reply on HN