Live data from Hacker News

Don't Use Mocks

joeblu.com

31–40 of 85 posts

Re: Don't Use Mocks

#31
post #14

There are entirely separate communities IMO when it comes to automated tests. There are the pushing-the-edge-of-excellence folks, constantly refining methods and approaches, who tend to be passionate about the holistic benefits of testing. And there are the folks who write convoluted tests that, when you dig into them, just confirm that String's .equals() works OK. DAO/database tests which have mocking going on to th…

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…

The compose stack tests (when engineered right), are the only ones which can reliably reproduce and test almost any bug or feature reliably.

In 2018 I could understand the aversion to them given how unbearably slow and flaky they could be but those problems are draining away with improved tooling and faster machines.

I think before long they'll be the default - a test that is 4 seconds slower and 30% more realistic will seem like a no brainer.

Re: Don't Use Mocks

#32
post #2

I feel that if most of your tests relies on mocks it is a symptom of a very side-effected programming style. If you cannot unit test most your business logic then you are probably mixing up your business level code with side-effecting code (like calling APIs or DBs). Personally I've found it better to split pure business logic and side-effecting logic as close to the edge (API endpoint handler) as possible. Then it i…

> business level code with side-effecting code (like calling APIs or DBs).

Sometimes the business logic is in DBs with stored procs.

Re: Don't Use Mocks

#33
post #4
post #2

I feel that if most of your tests relies on mocks it is a symptom of a very side-effected programming style. If you cannot unit test most your business logic then you are probably mixing up your business level code with side-effecting code (like calling APIs or DBs). Personally I've found it better to split pure business logic and side-effecting logic as close to the edge (API endpoint handler) as possible. Then it i…

If your database isn't involved in your business logic then you're probably significantly underutilizing capabilities of modern databases.

How is that so?

Re: Don't Use Mocks

#34

The point is: if your tests just assert which methods are called on dependencies with what arguments (or something close to that), they are extremely coupled and brittle. Almost any change in the implementation will require changing such tests. And by their nature, they probably test some minor low-level things, that are not all that valuable to assert anyway. Mocks enable and encourage this kind of testing. Better t…

> The point is: if your tests just assert which methods are called on dependencies with what arguments (or something close to that), they are extremely coupled and brittle.

I'll go further. These tests are worse than useless; they're harmful.

- They're the very definition of testing an implementation

- You will wasted a ton of time updating them when your implementation changes

- They give a false sense of security/productivity

Re: Don't Use Mocks

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

Re: Don't Use Mocks

#36
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 changes is one of the primary purposes of tests? Your simple business logic layer function converting one object into another is not going to be the problem, the database is

Re: Don't Use Mocks

#37
My goto simple example here for dumb mocks is a multiply function.

You are doing it wrong if you have:

MyMock.Mocks(myMultiplyFunc).WithArgs(3, 4).ToCall(myAddFunc).Times(3).WithArg(4).ExpectsResponse(12).

Your multiply func being backed by add is not important to the unit test for multiplying. If you change it to have special handling for bitshifting in different cases, your mock tests break. Badly.

Mocks add coupling. Coupling is brittle. There are other testing options available. Are mocks sometimes useful? Maybe. I've not needed a mock library in 10 years of Go development designing and building robustly tested distributed sytems at scale. Every time I've seen a mock used it is gross. You end up with SomeSAASMock that is auto-generated to provide all the special handling of the real calls to the SAAS.

Don't mock out the full SendGrid API. Make a dependency interface "SendEmail(userID int, content []byte) (SendGridResp, error)". Inject that. Now you just have MyFakeSendGrid structs in tests and you can have it return an error when you want, or not. It is really that simple.

Depending on how detailed your integration or acceptance tests are, you can have sinks that capture network calls and return stubbed data or call the actual service.

Re: Don't Use Mocks

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

Maybe more eloquently put:

https://martinfowler.com/articles/mocksArentStubs.html

Re: Don't Use Mocks

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

As a Python main I'm wondering if the difference has to do with a strictly typed language like the author's two examples, Go and Java, requiring more boilerplate and interface classes and so on, that in turn require more customization of the mock (since he writes that it "implements the API of what it replaces" which seems like it would be a strange thing to say about a python mock).

Re: Don't Use Mocks

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

A fake is a 'local' or lower fidelity implementation of the real thing. A array/memory backed DB instead of postgres, etc.

A mock is a cache for a desired return value (which is hopefully what the real interface would correctly return).

Edit: actually sethammons link is great

Post reply on HN