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

Too many mocks killed the test - Sw Crafters Lyon 2021

Too many mocks killed the test - Sw Crafters Lyon 2021

Jean-Marie Lamodière

May 26, 2021
Tweet

More Decks by Jean-Marie Lamodière

Other Decks in Programming

Transcript

  1. Too many mocks killed the test What Hexagonal Architecture has

    changed Icons made by Icongeek26, Freepik from www.flaticon.com Jean-Marie Lamodière - Backend tech lead @jmlamodiere @swcraftlyon Slow Fast, Focus
  2. WHY ? Locking Tests vs. TDD Development Locking Tests Development

    TDD +50% Icons made by Roundicons from www.flaticon.com “I mock almost nothing” - Kent Beck https://youtu.be/z9quxZsLcfo?t=1270
  3. WHY ? Icons made by Freepik from www.flaticon.com Refactor locking

    tests https://github.com/JMLamodiere/tdd-demo-forumphp2020 POO, sync 2 demo projects Tests first https://github.com/JMLamodiere/tdd-demo-swcraftlyon-scala POO, async
  4. WHY ? Icons made by Freepik from www.flaticon.com https://github.com/JMLamodiere/tdd-demo-forumphp2020 /Application

    /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo /Infrastructure /Symfony RunningSessionController RegisterRunningSessionDeserializer RunningSessionSerializer Technical Business Technical
  5. WHY ? Icons made by Freepik from www.flaticon.com https://github.com/JMLamodiere/tdd-demo-swcraftlyon-scala /Application

    /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider /Database PostgresRunningSessionRepo /Infrastructure /AkkaHttp RunningSessionPostController JsonSupport Technical Business Technical
  6. • A Functional Test describes a behaviour • A Unit

    Test locks an implementation Prejudice #1 Icons made by Freepik from www.flaticon.com Could you review my PR before I write my Unit Tests ?
  7. • A Functional Test describes a behaviour • A Unit

    Test locks an implementation Prejudice #1 Icons made by Roundicons from www.flaticon.com All tests describe an expected public behaviour Only the audience and the size of the covered area vary Test Desiderata - Kent Beck : https://kentbeck.github.io/TestDesiderata/
  8. “Unit Test” = 1 method of 1 class Prejudice #2

    Icons made by Freepik from www.flaticon.com
  9. “Unit Test” = 1 method of 1 class Prejudice #2

    Icons made by Roundicons, Smashicons from www.flaticon.com Polysemy! Wrong debate... “A DeveloperTest is the correct name for what the industry generally calls a UnitTest” - Ward Cunningham The Unit Test trap : https://drpicox.medium.com/the-unit-test-trap-4a83e4012b17
  10. • Test Pyramid = big Unit Test coverage • Unit

    Test = mock other classes Prejudice #3 Icons made by Freepik from www.flaticon.com
  11. • Test Pyramid = big Unit Test coverage • Unit

    Test = mock other classes Prejudice #3 Icons made by Roundicons, Smashicons from www.flaticon.com Favor fast and focused tests. Ex: The Practical Test Pyramid : https://martinfowler.com/articles/practical-test-pyramid.html Slow Fast, Focus Sociable Unit Test UI component test Unit Tests on Adapters
  12. Only functional tests have 3 steps: • Given • When

    • Then Prejudice #4 Icons made by Freepik from www.flaticon.com
  13. Only functional tests have 3 steps: • Given • When

    • Then Prejudice #4 Icons made by Roundicons from www.flaticon.com All tests follow the narrative structure: • Given = Arrange • When = Act • Then = Assert Setup Catalyst Resolution
  14. Prejudice #5 Icons made by Freepik from www.flaticon.com Checking the

    number of calls to all mocked methods increases my confidence. ->expects($this->exactly(1))->method('xxx') ->shouldBeCalledTimes(1)
  15. Prejudice #5 Checking the number of calls to all mocked

    methods increases my confidence ->expects($this->exactly(1))->method('xxx') ->shouldBeCalledTimes(1) Icons made by Roundicons, Smashicons from www.flaticon.com • Blurs the intent of the test • Locks implementation details • Impossible to write first
  16. WHY ? What to test ? Subject Under Test (S.U.T.)

    Arguments (IN) Return value (OUT) Test Calls Collaborator (IN) Collaborator (OUT) Assert Stub : willReturn() Spy : shouldHaveBeenCalled() Given When Then Then
  17. I must know the splitting between my classes before I

    write my tests Prejudice #6 Icons made by Freepik from www.flaticon.com
  18. I must know the splitting between my classes before I

    write my tests Prejudice #6 Icons made by Roundicons from www.flaticon.com • Prod classes splitting != test classes splitting • Start with an area with a known boundary
  19. WHY ? Icons made by Freepik from www.flaticon.com /Application /Command

    RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo /Infrastructure /Symfony RunningSessionController RegisterRunningSessionDeserializer RunningSessionSerializer Technical Business Technical 1st test: area with a known boundary
  20. Prejudice #7 Icons made by Freepik from www.flaticon.com If I

    don't mock my Entities / DTOs, too many tests will break if I add a field
  21. Prejudice #7 Icons made by Roundicons from www.flaticon.com If I

    don't mock my Entities / DTOs, too many tests will break if I add a field • Use test Factori(es) with optional fields • Getter not covered ? I remove it
  22. Prejudice #8 Icons made by Freepik from www.flaticon.com I can

    mock the libraries used on the Infrastructure side : • Http : Guzzle… • Database : Doctrine, Eloquent…
  23. Prejudice #8 Icons made by Roundicons, Smashicons from www.flaticon.com I

    can mock the libraries used on the Infrastructure side : • Http : Guzzle… • Database : Doctrine, Eloquent… • Coupled with the usage details of the lib • Assumptions about the way it behaves • Impossible to write first • No confidence when upgrading the lib
  24. WHY ? Infrastructure : Integration Tests Icons made by Freepik,

    Smashicons, Roundicons from www.flaticon.com QueryBuilder -> pure SQL MysqlRepository Docker mysql HttpRepository Wiremock Guzzle -> Symfony HttpClient Refactoring eg.
  25. WHY ? “Don’t mock what you don’t own” Icons made

    by Freepik, Smashicons, Roundicons from www.flaticon.com /Application /Command RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo Unit/Fast/Small tests Integration Mock No Mock!
  26. Prejudice #9 Icons made by Roundicons, smashicons from www.flaticon.com Functional

    Test = necessarily end to end • Slow • Brittle • Difficult to maintain • Harder to write first • Locks Infrastructure choices too soon Suggestion : mock Secondary Ports
  27. WHY ? Icons made by Freepik from www.flaticon.com /Application /Command

    RegisterRunningSession RegisterRunningSessionHandler /Domain WeatherProvider(Interface) RunningSession RunningSessionRepo(Interface) /Infrastructure /Http HttpAccuWeatherProvider CurrentConditionDeserializer /Database PostgresRunningSessionRepo /Infrastructure /Symfony RunningSessionController RegisterRunningSessionDeserializer RunningSessionSerializer Suggestion Functional Integration
  28. WHY ? Icons made by Freepik from www.flaticon.com Suggestion Functional

    Integration Outside-in Diamond 🔷 TDD - Thomas Pierrain http://tpierrain.blogspot.com/2021/03/outside-in-diamond-tdd-1-style-made.html
  29. @jmlamodiere Thanks! Development Locking tests Development TDD +50% Icons made

    by Roundicons, Freepik from www.flaticon.com It’s your turn ! • //Given //When //Then • Even if I write a test afterwards, I only write what I would have been sure of before https://github.com/JMLamodiere/tdd-demo-forumphp2020 https://github.com/JMLamodiere/tdd-demo-swcraftlyon-scala @swcraftlyon