Live data from Hacker News

Prefer Fakes over Mocks

tyrrrz.me

11–20 of 125 posts

Re: Prefer Fakes over Mocks

#11
The fatal flaw is that you’re really introducing a new class which may have its own behaviour problems. Now your test is implicitly testing the test class. I also prefer to see explicit mocking than just trust that the fake does what it says it will. How do I know without looking whether the fake store method REALLY stores the doc, or whether someone set it up to just return OK? And how do you test error handling - make another fake for every error scenario?

Re: Prefer Fakes over Mocks

#12

The fatal flaw is that you’re really introducing a new class which may have its own behaviour problems. Now your test is implicitly testing the test class. I also prefer to see explicit mocking than just trust that the fake does what it says it will. How do I know without looking whether the fake store method REALLY stores the doc, or whether someone set it up to just return OK? And how do you test error handling - m…

Mocks have the same problem. You create something new, that can have uninteneded behavior. Even worse, if you are not perfectly familiar with the mocking framework, you maybe won't even notice it.

The good thing about (simple) fakes is, that you can see all the code in a very small class. No complicated library, that does something funky in a special case.

Mocking can be very useful though, but it can get too complicated very quickly.

Re: Prefer Fakes over Mocks

#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 acceptance testing is a more useful tool for detecting user facing defects as it also tests the developers assumptions about functionality.

Re: Prefer Fakes over Mocks

#14

The fatal flaw is that you’re really introducing a new class which may have its own behaviour problems. Now your test is implicitly testing the test class. I also prefer to see explicit mocking than just trust that the fake does what it says it will. How do I know without looking whether the fake store method REALLY stores the doc, or whether someone set it up to just return OK? And how do you test error handling - m…

> How do I know without looking whether the fake store method REALLY stores the doc, or whether someone set it up to just return OK?

Why would you not look into the fake implementations? If it's just a two liner that takes the parameters and writes them to disk, then that's a LGTM from me. You would not test every getter/setter method in any of your classes, would you?

If it's more complex than this, you can absolutely write tests for your fakes. In many cases fake data-stores use tested backends, and tested client libraries. If the client wrapper is complex enough then you can/should test it as well.

Re: Prefer Fakes over Mocks

#15

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 syntax does not scale. Your 5 lines of setup in one test does not help you in a different test class. So it gets repeated.

Soon you might find that the Fake is easier to read, easier to maintain, and fewer lines of code than all the mocks.

As the article says: "their self-contained nature makes them reusable as well, which lends itself to better long-term maintainability." Not all our code is "do it quickly and forget about it", especially where you see that same thing or minor variations of it done over and over again in related tests.

Mocks win here when you do something different, once only. Fakes win in the opposite cases.

> I can see fakes being useful in certain cases,

This is true, but it's also true that Fakes are _underused_ in general in in the .NET world. People reach for mocking frameworks as if they are the only tool.

Re: Prefer Fakes over Mocks

#16
post #12

The fatal flaw is that you’re really introducing a new class which may have its own behaviour problems. Now your test is implicitly testing the test class. I also prefer to see explicit mocking than just trust that the fake does what it says it will. How do I know without looking whether the fake store method REALLY stores the doc, or whether someone set it up to just return OK? And how do you test error handling - m…

Mocks have the same problem. You create something new, that can have uninteneded behavior. Even worse, if you are not perfectly familiar with the mocking framework, you maybe won't even notice it. The good thing about (simple) fakes is, that you can see all the code in a very small class. No complicated library, that does something funky in a special case. Mocking can be very useful though, but it can get too complic…

Mocks are essentially just “calling this function on the mock object during this test returns this result”, though, right? At least, the ones I write are. No state, no logic, no real ‘behaviour’. As soon as you introduce a fake that really has an underlying state and maybe some kind of validation logic (assuming that you want tests to make sure you can’t insert nonsense/retrieve non-existent stuff), you’ve introduced a ton of new and completely meaningless failure points.

Re: Prefer Fakes over Mocks

#17

How are fakes, as described in this article, not also implementation-aware testing?

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 data.

The only things that are missing there are real life latency or maybe exceptions because of connectivity issues.

Re: Prefer Fakes over Mocks

#18
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…

But if we didn't care about defects, developers could confidently make changes to existing code without having tests.

The end goal is still avoiding defects, helping developers is just the "middle-man".

Re: Prefer Fakes over Mocks

#19

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.

I completely agree with you

Re: Prefer Fakes over Mocks

#20
post #12

Earlier quoted context omitted.

Mocks have the same problem. You create something new, that can have uninteneded behavior. Even worse, if you are not perfectly familiar with the mocking framework, you maybe won't even notice it. The good thing about (simple) fakes is, that you can see all the code in a very small class. No complicated library, that does something funky in a special case. Mocking can be very useful though, but it can get too complic…

Mocks are essentially just “calling this function on the mock object during this test returns this result”, though, right? At least, the ones I write are. No state, no logic, no real ‘behaviour’. As soon as you introduce a fake that really has an underlying state and maybe some kind of validation logic (assuming that you want tests to make sure you can’t insert nonsense/retrieve non-existent stuff), you’ve introduced…

You're totally right.

But think about a blob storage class that has two methods, ReadOneFile(), ReadMultipleFiles().

You have one test that just mocks ReadOneFile(string fileName) and doesn't mock the ReadMultipleFiles(). You now change the implementation of the System Under Test (SUT) to use once the ReadMultipleFile(string[] fileNames) call instead of three times the ReadOneFile(). Now your test fails, but the implementation of the SUT is perfectly valid. You need to rewrite your test.

If you would use a fake, the test would stay green, without changing. The test with the fake is less specific to the implementation, and helps you better with refactoring/changing your code.

And additionally in this example ReadOneFile() is called three times, and is expected to return three different results. So even your mock needs some logic to handle that.

Post reply on HN