Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Thou shalt not mock

Thou shalt not mock

Mocking frameworks like Mockito are considered harmful, by myself ;-). This is a concise presentation that just barely touches the subject at hand.

See https://github.com/Danny02/do-not-mock-examples for some code examples.

Daniel Heinrich

September 30, 2022
Tweet

More Decks by Daniel Heinrich

Other Decks in Programming

Transcript

  1. Inhalt • Intro • Layered architecture • Define testing terms

    used • Testing Commandments • About mocking • Code Review • … • Profit!
  2. • Please do not feel offended • Intentionally provocative •

    Yes edge cases exist • I also use Mockito in my code in some cases • Let’s not fight over terms
  3. Testing a Layered Architecture • Use Cases define an API

    (Java interface) • API definition includes behavior (i.e. protocols) • used by controllers: CLI, REST, UI • Is normally quite stable • Testing those APIs is sometimes called • BDD • Acceptance Tests • The most important Tests, guarantee the global correctness of the application
  4. Terms used “The Big Three” patterns to test interactions *

    • Stub: dumb piece software, which returns a specific value • Fake has the same behavior as the real thing and contains a state. Its implementation is much simpler and runs in memory (beware of simulators). • Spy empty implementation which records the way it was called Mocks are generated objects which can do all the above • Tools like Mockito make stubs & spies easy but fakes are hard to create • Fakes should be the default! * somewhat better definitions on http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html
  5. Testing Commandments • Do not use Mockito • Use the

    complete object-graph • Fake all external dependencies • keep tests „immutable“ • Hide dependencies behind small interfaces • Test the fakes for correct behavior • Delete other tests when implementation changes
  6. Why mocking is bad Testing(coding) is also a social problem

    not just technical • Unclean code is hard to test • Mocks make it easy to test hard to test code • People always follow the path of least resistance Common problems • Mocks differ in behavior from the real thing (don’t simulate behavior) • They easily give the impression that everything is tested even if nothing is • They introduce a strong coupling to the implementation => • Test become unstable • Unclear for the next developer how to fix the tests correctly • Knowledge about the implementation details is required (try & error) • What does it tell us that method was called 17 times
  7. Mockito is a hack for unchangeable Code https://site.mockito.org/javadoc/current/org/mockito/Mockito.html Abusing it

    leads to overspecified, less maintainable tests. Yet another controversial feature Real spies should be used carefully and occasionally, […] when dealing with legacy code. […] we thought partial mock is a code smell It's quite an advanced feature and typically you don't need it to write decent tests. However, it can be helpful for working with legacy systems. may decrease test readability […]. Also it may reduce defect localization […] OOP is more less tackling complexity by dividing the complexity into […] objects. How does partial mock fit into this paradigm? Well, it just doesn't […] this is not the way you want to design your application. Smart Mockito users hardly use this feature because they know it could be a sign of poor tests. Don't harm yourself. WARNING: This should be rarely used in unit testing. every time a mock returns a mock a fairy dies. What might be reason your test needs non-standard mocks? Is the code under test so complicated that it requires non-standard mocks? Wouldn't you prefer to refactor the code under test so it is testable in a simple way? This feature should rarely be required for regular clean code! Leave it for legacy code. Mocking a mock to return a mock, to return a mock, (...), to return something meaningful hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern). Beware that naming mocks is not a solution for complex code which uses too many mocks or collaborators. If you have too many mocks then refactor the code so that it's easy to test/debug without necessity of naming mocks.
  8. But … • Those are no unit tests • So

    what, they are more useful than all “unit” tests • Kent Beck would not approve * • So time-consuming to write all those fakes • Are reused for all tests • You can not fake JDBC • Hide behind a small interface • Any other reason • Fix code smells through refactoring, not Mockito * see sociable unit tests https://martinfowler.com/bliki/UnitTest.html