Should you only mock types you own?
Asked Answered
O

7

62

I read through TDD: Only mock types you own entry by Mark Needham and would like to know if this is best practice or not?

Please note that he is not against mocking, but against mocking directly - he does say that writing a wrapper and mocking that is fine.

Overact answered 15/12, 2009 at 10:0 Comment(3)
I find this article to be very helpful in explaining this issue: davesquared.net/2011/04/dont-mock-types-you-dont-own.htmlEusebiaeusebio
A more modern explanation: github.com/testdouble/contributing-tests/wiki/…Softspoken
Plugging my own explanation: medium.com/@xpmatteo/how-i-learned-to-love-mocks-1-fb341b71328Commutation
A
38

Depends whether you mean mock or mock™…

Given you are just using a mock framework (as eg Mockito) to create stubs, then creating stubs of types you don't own is totally okay and reasonable.

If however, you are using a mock framework (as eg Mockito) to create mock™ objects, then you best literally follow the advice of the mock™ evangelists. Personally I lost touch to that movement, so I cannot tell you whether Mark Needham's advice is to be considered kosher or not.

Irony aside, what Mark writes about mocking of EntityManagers in Hibernate sounds reasonable by itself. But I doubt that we can generalize a rule like "never mock types you don't own" from that specific case. Sometime it might make sense, sometimes not.

Absorptance answered 15/12, 2009 at 10:41 Comment(3)
Can you clarify the difference between mock and mock™? I know it's been over a decade(!), but it still seems relevant.Spray
I think he's used those 2 terms because in mockito mock is also a stubOrwin
@Orwin but Mockito wiki states "Do not mock types you don't own" github.com/mockito/mockito/wikiRabjohn
H
40

My answer is "no". You should mock anything that makes sense in the context of a given unit test. It should not matter if you "own" the mocked type or not.

These days, in a Java or .NET environment everything (and I really mean everything) can be easily mocked. So, there is no technical reason to go to the trouble of first writing extra wrapper code.


Some additional ideas I have been thinking about recently (November 2010), that show how illogical to "only mock types you own" can be:

  1. Suppose you do create a wrapper for a third-party API, and then you mock the wrapper in unit tests. Later, however, you figure the wrapper can be reused in another app, so you move it to a separate library. So now the wrapper is no longer "owned" by you (since it is used in multiple apps, potentially maintained by different teams). Should developers create a new wrapper for the old one?!? And keep doing it recursively, adding layer upon layer of essentially useless code?
  2. Suppose somebody else already created a nice wrapper for some non-trivial API and made it available as a reusable library. If said wrapper is just what I need for my specific use case, should I first create a wrapper for the wrapper, with a nearly identical API, just so I will "own" it?!?

For a concrete and realistic example, consider the Apache Commons Email API, which is nothing more than a wrapper for the standard Java Mail API. Since I don't own it, should I always create a wrapper for the Commons Email API, whenever I write unit tests for a class which needs to send e-mail?

Hefter answered 17/12, 2009 at 16:15 Comment(3)
Sorry, But I don't know why this is upvoted more than https://mcmap.net/q/320581/-should-you-only-mock-types-you-own That answer explains it well. The rule makes sense. A library you own doesn't mean defined in the same package.You know when an implementation is changed for a library you made. Even if it is an opensource library and if you know when it changes, well, go ahead and mock it. But that gets tough when you don't know when implementation changes. Hell, sometimes the api might change, that's why we use wrappers in the first place.Semitone
@Amanuel, this comment says the opposite.Hefner
You probably don't need a wrapper for the whole email API, but it may be helpful to write a wrapper that does just the things that your application wants and leaves the "sending an email" part as an implementation detail of a single class. So that class effectively wraps the email API. In general, try to avoid sprinkling 3rd party APIs all over your code but sometimes it's unavoidable, e.g., SLF4J.Cabalism
A
38

Depends whether you mean mock or mock™…

Given you are just using a mock framework (as eg Mockito) to create stubs, then creating stubs of types you don't own is totally okay and reasonable.

If however, you are using a mock framework (as eg Mockito) to create mock™ objects, then you best literally follow the advice of the mock™ evangelists. Personally I lost touch to that movement, so I cannot tell you whether Mark Needham's advice is to be considered kosher or not.

Irony aside, what Mark writes about mocking of EntityManagers in Hibernate sounds reasonable by itself. But I doubt that we can generalize a rule like "never mock types you don't own" from that specific case. Sometime it might make sense, sometimes not.

Absorptance answered 15/12, 2009 at 10:41 Comment(3)
Can you clarify the difference between mock and mock™? I know it's been over a decade(!), but it still seems relevant.Spray
I think he's used those 2 terms because in mockito mock is also a stubOrwin
@Orwin but Mockito wiki states "Do not mock types you don't own" github.com/mockito/mockito/wikiRabjohn
A
33

I like the explanation the Mockito project gives to this question.

Don't mock type you don't own!

This is not a hard line, but crossing this line may have repercussions! (it most likely will)

  1. Imagine code that mocks a third party lib. After a particular upgrade of a third library, the logic might change a bit, but the test suite will execute just fine, because it's mocked. So later on, thinking everything is good to go, the build-wall is green after all, the software is deployed and... Boom
  2. It may be a sign that the current design is not decoupled enough from this third party library.
  3. Also another issue is that the third party lib might be complex and require a lot of mocks to even work properly. That leads to overly specified tests and complex fixtures, which in itself compromises the compact and readable goal. Or to tests which do not cover the code enough, because of the complexity to mock the external system.

Instead, the most common way is to create wrappers around the external lib/system, though one should be aware of the risk of abstraction leakage, where too much low level API, concepts or exceptions, goes beyond the boundary of the wrapper. In order to verify integration with the third party library, write integration tests, and make them as compact and readable as possible as well.

Atonic answered 11/8, 2015 at 9:51 Comment(7)
What does it mean : "abstraction leakage, where too much low level API, concepts or exceptions, goes beyond the boundary of the wrapper" ?Dictation
Unit tests are all about isolation. I don't think mocking is a problem as long as you've got accountability in your integration tests. Wrapping for the sake of testing can introduce its own complexities: unless they're trivial, at some point your wrappers will also need to be tested.Ownership
For what's its worth, I think this should be the accepted answer.Semitone
I don't like this answer. Unit tests should test the smallest unit of work that YOU wrote. They SHOULD isolate themselves from third party dependencies. Use Integration tests to shake out these problems instead. I don't want HTTP calls and DB calls from 3rd party libs slowing my unit tests down.Klarrisa
I completely do not understand the 1st point you quoted @H6. I do agree that with the upgrade of 3rd party library the test will pass, but what are they suggesting as an alternative? Creating a wrapper on the 3rd party lib, and mocking it. So what is the logic here? I mean, in their proposed solution we will still have the same problem, the test wont discover 3rd party change because we mocked the wrapper that calls them, so what is the difference except for that we just created an extra function that doesn't do nothing?Lutyens
@WesGrant that is the whole point of this advice: you want your unit tests to test isolated… units of code. If that unit of code depends on a 3rd-party library, it cannot be isolated because its behavior depends on something you don’t control. So either you wrap that 3rd-party library into an intermediate layer that you control, or you consider that this piece of code is already the wrapper (e.g. it’s a DAO/repository). In both cases that 3rd-party library integration should be tested in integration tests.Ogdan
Too much abstraction (e.g. lib wrappers) make code harder to write and (most importantly) read. Libs should be wrapped only when we're pretty sure that in the future we'll need to change library (e.g. storage from SQL to NoSQL, or the library undergoes heavy development which may break backwards compatibility - it's easier to fix the wrapper than all pieces of code)Polk
M
11

I was going to say "no" but having had a quick look at the blog post I can see what he is on about.

He talks specifically about mocking EntityManagers in Hibernate. I am against this. EntityManagers should be hidden inside DAOs (or similar) and the DAOs are what should be mocked. Testing one line calls to EntityManager is a complete waste of your time and will break as soon as anything changes.

But if you do have third party code that you want to test how you interact with it, by all means.

Maynard answered 15/12, 2009 at 10:5 Comment(0)
R
3

IMHO, the question of ownership is irrelevant.

The relevant question is the one of coupling, i.e. what does your test code specify. You certainly don't want test code which specifies details of the API of some library that you happen to use. This is what you get when you e.g. use Mockito to mock the library directly in your test class.

A widespread solution proposal for this problem is to create a wrapper around the library and then to mock the wrapper. But this has the following drawbacks:

  • The code inside the wrapper is not tested.
  • The wrapper may be an imperfect abstraction, so the API of the wrapper may need to be changed. If you mocked the wrapper in many tests, you have to adapt all these tests.

So instead, I would recommend to decouple tests from interfaces in productive code altogether. Don't put the mocks into the test code directly, but create a separate stub class which implements or mocks the productive interface. Then add a second interface to the stub which allows the tests to do the necessary setup or assertions. Then you only need to adapt one class in case the productive interface changes – and you could even afford to mock/stub the interface of a library that is complex or changes frequently.


Note: All this is assuming that it is in fact necessary to use a mock or stub. I didn't discuss this question here because it was not in scope of the OP's question. But really ask yourself if you have to use mocks/stubs at all. In my experience, they are overused...

Ravage answered 5/3, 2018 at 13:14 Comment(2)
I was going to upvote for the first part... but I cannot agree with the last paragraph. Creating (probably pointless, single implementation) interfaces and them mocking them is not the solution, nor is it to do "hand mocking/stubbing". Instead, simply avoid mocking/stubbing altogether and write tests for meaningful externally observable behavior, tests that focus on the "what", not the "how".Flageolet
I agree. I've added a disclaimer that the question of whether to mock at all is important but out of scope here.Ravage
T
0

I agree with Mark is saying. You can not unfortunately mock everything and there are somethings you don't want to mock, just because your normal use of it is a black box.

My rule of thumb is Mock things that will make the test fast but won't make the test flaky. Remember not all fakes are the same and Mocks are not Stubs.

Themistocles answered 15/12, 2009 at 10:6 Comment(1)
Actually, you CAN mock everything. To me, the real difference is not between mocks and stubs, but between strict and non-strict expectations. And the expectations associated to any mock object can be either strict or not.Flageolet
B
0

I'm certainly from a minority, but I regard Mocking as a Code Smell and use dependency injection instead if possible. The rationale is that mocking is basically a workaround for testing some hard to test code. Mocks weaken tests because they behave (at best) like a specific version of a library. If the library change, your test loose all it's checking value.

You can see reading the above that I'm using Mark Needham's own arguments, but not for saying you should not mock object's you don't own, but that you shouldn't Mock at all...

OK, if dependency injection is not an option, then let's mock... but then you have to understand that your test is a fake and won't behave like production code. That's not a real unit test, just a partially faked one. If possible, you can make it less so by adding tests that checks that behavior is as expected for the Mocked Objects.

Butyraceous answered 10/7, 2010 at 23:12 Comment(4)
I think maybe your definition of either "dependency injection" or "mocking" is different that the usual. They are not mutually exclusive, rather, they are complimentary: sometimes you inject the real implementation of a dependency (production, integration testing), and sometimes you inject mocks (unit testing).Ruffled
@Ladlestein: I don't believe so, but maybe. I use "Mocking" when I'm changing behavior of something that is not an explicit parameter (typically some global library). I speak of "Dependency Injection" when I'm refactoring code to replace an implicit parameter with an explicit object provided as a parameter (either through tested object constructor or of some method). And indeed when provinding some test object I do not speak of Mock any more but of Stubs (if it's not a real implementation) or of Fakes (real implementation but simplified for testing purpose).Butyraceous
@Butyraceous I agree. Many times I see a product (say DB driver, severless function, etc) and shortly there will be a mock library that is designed to test things using it (in ideal world). But in reality the library will go out of sync sooner or later (or even internal mocks will go out of sync after the library update) and suddenly the tests are not only not helpful, but rather harmful. When using a mock library - you essentially test how good the mock library is, not your code. I'm for DI all the way. cosmicpython.com/book/chapter_06_uow.html (some nice thoughts on the subject here)Flannelette
@Butyraceous and one more thing - there is mock libraries like Sinon.JS in nodejs that helps stub and monkeypatch things and there are libraries similar to moq library for Go by Matt Ryer, what basically generates mocks for interfaces. The former are for mocking and the later basically for creating fakes for DI. Both called are called mock libraries, but there is a HUGE difference between them. sinonjs.org github.com/matryer/moqFlannelette

© 2022 - 2024 — McMap. All rights reserved.