Live data from Hacker News

Prefer Fakes over Mocks

tyrrrz.me

41–50 of 125 posts

Re: Prefer Fakes over Mocks

#41
Even more important, IMO, regardless of whether you're mocking or faking, is to not mock or fake objects that you own. Only mock/fake truly external dependencies. The nice property you get with this is true tests of integration and interoperability between your modules, that are actually calling into each other. Only at the leaf nodes is anything mocked or faked, and that's when it leaves your ownership.

Re: Prefer Fakes over Mocks

#42
post #17

Earlier quoted context omitted.

Because they don't just implement a part of the interface (just one store method, or just one of two load methods). They try to create a fully functional fake of the original class. In this case instead of storing the blobs via a REST interface or a database connection, it just keeps it in memory. So it should mostly behave like the real implementation, but is not suitable for production, as it doesn't persist the da…

>> .. fully functional fake of the original class. So they are coupled to the implementation of the object in any case!

I’d say rather that they’re coupled to the behaviour of the object.

Re: Prefer Fakes over Mocks

#43
post #17

Earlier quoted context omitted.

Because they don't just implement a part of the interface (just one store method, or just one of two load methods). They try to create a fully functional fake of the original class. In this case instead of storing the blobs via a REST interface or a database connection, it just keeps it in memory. So it should mostly behave like the real implementation, but is not suitable for production, as it doesn't persist the da…

> Because they don't just implement a part of the interface (just one store method, or just one of two load methods). They try to create a fully functional fake of the original class. So shouldn't fakes have their own tests as well? Mocks don't need tests (at least in C# with a framework) because no new class is ever written. Anyway most of these issues are inherently linked to the nature of OOP and are a direct trad…

Why do fakes need tests, but mocks don't?

In one case you create the class on your own, in the other case the mocking framework does that for you on the fly. With both approaches you can do very basic or very complicated things.

Or do you have a rule in your company that every class needs a test? Maybe this rule is the problem.

Re: Prefer Fakes over Mocks

#44

It seems to me that a Fake is really a Mock, and Mocks became this unholy dynamic framework stuff. I'm not a fan of dynamic mocks where the test code has the mocked implementation because it is super brittle. Instead, a "fake" (i.e. a mock as I understood them) is an alternatively implementation of an interface. There are a lot of really good "fakes" out there. Fake file system which lets you simulate disk failures.…

The problem with those alternative implementations is that they turn your unit tests into expensive and complicated integration tests. In a complex system getting a socket into the state you're interested in can be many times harder than the test itself. "Magic" mocks make it cheap and easy.

Re: Prefer Fakes over Mocks

#45
post #13

A tangent, and somewhat philosophical: is "The primary purpose of software testing" really "to detect any potential defects in a program before it reaches its intended consumers"? I would argue that whilst that is a commonly held belief, and certainly true for some tests of business logic, the main value and reason for testing is to allow developers to confidently make changes to existing code. In my experience user…

[deleted]

Re: Prefer Fakes over Mocks

#46

Even more important, IMO, regardless of whether you're mocking or faking, is to not mock or fake objects that you own. Only mock/fake truly external dependencies. The nice property you get with this is true tests of integration and interoperability between your modules, that are actually calling into each other. Only at the leaf nodes is anything mocked or faked, and that's when it leaves your ownership.

You're choosing some place in between the integration and unit testing where your test will live. But this choice will not make sense for everyone. If your project includes its own persistence functions, you'll likely want a test to get a "CouldntWriteException" immediately from a mock rather than go through all the layers (that you own) to get an IO error (you don't own the fs dependency) and all layers back. It's a tiny difference for a single test, but once you get to hundreds, it will be a difference between devs getting immediate feedback and "going for coffee, my code is testing" which really impacts productivity.

Re: Prefer Fakes over Mocks

#47

Even more important, IMO, regardless of whether you're mocking or faking, is to not mock or fake objects that you own. Only mock/fake truly external dependencies. The nice property you get with this is true tests of integration and interoperability between your modules, that are actually calling into each other. Only at the leaf nodes is anything mocked or faked, and that's when it leaves your ownership.

Yes! Mocking internal dependencies also has the side effect of ossifying the internal interface between the two objects, which is never as well-designed as the external ones IME.

Also, in dynamic languages, you might even have tests that don’t break when you change (or sometimes even delete) the dependency because the mock was correct. That leads to a false sense of confidence.

Re: Prefer Fakes over Mocks

#48
I'm a little surprised this article and none of the contents here at the time of this writing mentioned inheritance.

The core reason I find OOP to be superior for most classes of business application development in general—and web development in particular—is that external dependencies and other high cost interfaces can be delegated to their own method or instance variable then called. In general, I avoid inheritance if there is a way to approach a problem with composition, but testing via fakes are much more reliable to make by inheriting the original class and overriding a method or setting a default initialization parameter then calling the rest of the constructor. This takes the pain out of so many parts of testing that it's truly hard to understate.[0]

For example, say a library has a class that calls out to a third party service like S3 and an instance of that class is used in a business object in order to persist data. By introducing a fake that inherits from the library's class but overrides it's persistence method to effectively be a noop the rest of the validation, calculation, and other side effects that the instance does is conserved without the downside of waiting on a network call. It's not perfect, for example it could miss validation or side effects that only exist on the external service (e.g., S3 could change a mime type based on some crummy AWS logic) but it's a hell of a lot better than a mock that constantly lies to you about what its done. Furthermore, it's actually extremely simple to code up, unlike pure fakes that need to return hard coded values for certain method calls.

I know that something akin to this is theoretically possible in functional languages, but I've found that in practice it's more difficult. Though I appreciate other areas where functional languages shine, including situations with testing.

It's kinda hard to discuss because it really depends on so much context and good judgement and I've seen truly great development teams use languages like Scala in situations where I would have used Python with Numpy / Cython for speed. So don't take this as some hard and fast pronouncement. Just the general observations of someone that's been coding for decades and is reasonably well paid.

[0] I think the primary reason that I prefer integration testing over unit testing is that I've adapted to its shortcomings by the above approach.

Re: Prefer Fakes over Mocks

#49

Not particularly convincing. Mocks work well because you can quickly define them in a given unit test and forget about it. I can see fakes being useful in certain cases, but only just in certain cases. Could be my inexperience with C#, but it didn't do justice describing the point in code samples.

> Mocks work well because you can quickly define them in a given unit test and forget about it. They do, yes. But: * the mock syntax is complex and verbose. e.g. "repo.Setup(x => x.Method(It.IsAny (), It.IsAny >())) .ReturnsAsync(() => ...." is not the easiest syntax. The syntax for a fake is just regular old "class FakeFoo: IFoo" with trivial method implementations and no library needed to make it work. * the mock s…

AFAICT you’re not talking about mocks in general, only about automated Moq-style frameworks?

A trivial mock implementation is less complex than what OP refers to as “fakes”.

Re: Prefer Fakes over Mocks

#50

I'm a little surprised this article and none of the contents here at the time of this writing mentioned inheritance. The core reason I find OOP to be superior for most classes of business application development in general—and web development in particular—is that external dependencies and other high cost interfaces can be delegated to their own method or instance variable then called. In general, I avoid inheritance…

The benefits you describe for OOP can be achieved in FP through function composition. DI doesn't have to mean you set up a container, you know.

> I know that something akin to this is theoretically possible in functional languages, but I've found that in practice it's more difficult.

Could you explain what you think is hard about it?

Post reply on HN