Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Wann soll ich mocken?

356 Aufrufe

Veröffentlicht am

Die Slides zu meiner Session "Wann soll ich mocken?" auf den XP Days Germany 2016.

Abstract:

Mocking hat sich als wichtiges Hilfsmittel etabliert, um Teilfunktionalität isoliert testen zu können. Skeptiker werfen dem Ansatz allerdings vor, der Wartbarkeit zu schaden: die Tests würden schlechter lesbar, das Refaktorisieren des Codes schwieriger. Wann sind diese Einwände berechtigt und wie können wir damit umgehen.

- Mocking Anti-Patterns und "Best Practices"
- Alternative Designs, die Mocking obsolet machen
- Entscheidungskriterien wann Mocking Sinn macht und wann nicht

Grundlegende Erfahrungen mit einem Mockingframework sind sinnvoll. Zur Veranschaulichung hab ich konkrete Codebeispiele im Gepäck.

Veröffentlicht in: Software
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Wann soll ich mocken?

  1. 1. Wann soll ich mocken? XP Days Germany David Völkel 21.11.2016
  2. 2. @davidvoelkel @softwerkskammer @codecentric TDD & Design
  3. 3. SCHICHTEN TESTEN?
  4. 4. INTEGRIERTER TEST
  5. 5. Unittest Mock MOCKING
  6. 6. Unittest Mock MOCKING
  7. 7. Unittest Mock MOCKING
  8. 8. aufwendiges Setup Fehlerfindung # Testfällen Langsames Feedback Refactorability sinkt Isolationsaufwand Zu wenig Nutzen Lesbarkeit TRADE-OFF ZU GROSS vs ZU KLEIN
  9. 9. Woran orientieren ?
  10. 10. IDEOLOGIEN MOCKISTS CLASSICISTS "Mocks Aren't Stubs", Martin Fowler
  11. 11. TRADE-OFFS statt IDEOLOGIEN!
  12. 12. USE CASES MOCKISTS CLASSICISTS Anbindung Drittsysteme
  13. 13. USE CASES MOCKISTS CLASSICISTS Anbindung Drittsysteme Bedingte Interaktionen
  14. 14. USE CASES MOCKISTS CLASSICISTS SWEETSPOT Anbindung Drittsysteme Bedingte Interaktionen
  15. 15. USE CASES MOCKISTS CLASSICISTS SWEETSPOT Anbindung Drittsysteme Bedingte Interaktionen Geringer Nutzen
  16. 16. VERMEIDEN USE CASES MOCKISTS CLASSICISTS SWEETSPOT Anbindung Drittsysteme Bedingte Interaktionen Geringer Nutzen
  17. 17. VERMEIDEN MOCKING SWEETSPOT „BEST PRACTICES“
  18. 18. VERMEIDEN
  19. 19. „DONT MOCK VALUES!
  20. 20. „DON‘T MOCK VALUES! new Value()
  21. 21. „DON‘T MOCK VALUES! new Value() TestDataBuilderForValue .withDefaults() .withField(“1“)
  22. 22. INTEGRATION OPERATION SEGREGATION PRINCIPLE "Integration Operation Segregation Principle", Ralf Westphal "Die kniffligen Fälle beim Testen - Sichtbarkeit", Stefan Lieser
  23. 23. INTEGRATION OPERATION SEGREGATION PRINCIPLE public void sendMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String title = customer.getSex() == Sex.MALE ? "Mr" : customer.getMaritialStatus() == MaritialStatus.MARRIED ? "Mrs" : "Ms"; String content = "Hello " + title + ". " + customer.getName() + ",nn" + "We have a special offer for you.nn" + "Best regards,n" + "ACME Customer Service"; mailService.sendMail(email, content); }
  24. 24. public void sendMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String title = customer.getSex() == Sex.MALE ? "Mr" : customer.getMaritialStatus() == MaritialStatus.MARRIED ? "Mrs" : "Ms"; String content = "Hello " + title + ". " + customer.getName() + ",nn" + "We have a special offer for you.nn" + "Best regards,n" + "ACME Customer Service"; mailService.sendMail(email, content); } INTEGRATION OPERATION SEGREGATION PRINCIPLE
  25. 25. public void sendMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String title = customer.getSex() == Sex.MALE ? "Mr" : customer.getMaritialStatus() == MaritialStatus.MARRIED ? "Mrs" : "Ms"; String content = "Hello " + title + ". " + customer.getName() + ",nn" + "We have a special offer for you.nn" + "Best regards,n" + "ACME Customer Service"; mailService.sendMail(email, content); } INTEGRATION OPERATION SEGREGATION PRINCIPLE
  26. 26. public void sendMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String content = renderContent(customer); mailService.sendMail(email, content); } private String renderContent(Customer customer) { String title = customer.getSex() == Sex.MALE ? "Mr" : customer.getMaritialStatus() == MaritialStatus.MARRIED ? "Mrs" : "Ms"; return "Hello " + title + ". " + customer.getName() + ",nn" + "We have a special offer for you.nn" + "Best regards,n" + "ACME Customer Service"; } INTEGRATION OPERATION SEGREGATION PRINCIPLE
  27. 27. public void sendMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String content = renderContent(customer); mailService.sendMail(email, content); } private String renderContent(Customer customer) { String title = customer.getSex() == Sex.MALE ? "Mr" : customer.getMaritialStatus() == MaritialStatus.MARRIED ? "Mrs" : "Ms"; return "Hello " + title + ". " + customer.getName() + ",nn" + "We have a special offer for you.nn" + "Best regards,n" + "ACME Customer Service"; } TESTS? N Unittests
  28. 28. public void sendMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String content = renderContent(customer); mailService.sendMail(email, content); } private String renderContent(Customer customer) { String title = customer.getSex() == Sex.MALE ? "Mr" : customer.getMaritialStatus() == MaritialStatus.MARRIED ? "Mrs" : "Ms"; return "Hello " + title + ". " + customer.getName() + ",nn" + "We have a special offer for you.nn" + "Best regards,n" + "ACME Customer Service"; } TESTS? 1 Integrierter Test N Unittests
  29. 29. PUSH LOGIC DOWN THE STACK Siehe "The Failures of “Intro to TDD”" - Justin Searls
  30. 30. PUSH LOGIC DOWN THE STACK
  31. 31. SWEETSPOT
  32. 32. public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); return "Welcome " + username; } else { return "Username ' " + username + "' " + "already taken, please choose another"; } } BEDINGTE INTERAKTION
  33. 33. SYSTEM GRENZEN 3rd Party Service Adapter
  34. 34. SYSTEM GRENZEN 3rd Party Service Mock
  35. 35. OUTSIDE-IN DESIGN
  36. 36. OUTSIDE-IN DESIGN Alternative “Fake it“
  37. 37. BEST PRACTICES
  38. 38. NO OVERSPECIFICATION!
  39. 39. NO OVERSPECIFICATION! “Specify exactly what should happen but no more”
  40. 40. REIHENFOLGE?
  41. 41. COMMAND & QUERY SEPARATION REIHENFOLGE IMMER NÖOTWENDIG? public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); ... } else { ... } }
  42. 42. COMMAND & QUERY SEPARATION REIHENFOLGE IMMER NÖOTWENDIG? public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); ... } else { ... } }
  43. 43. COMMAND & QUERY SEPARATION REIHENFOLGE IMMER NÖOTWENDIG? public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); ... } else { ... } }
  44. 44. COMMAND & QUERY SEPARATION REIHENFOLGE IMMER NÖOTWENDIG? public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); ... } else { ... } } @Test public void signup() throws Exception { ... when(userDB.findUserBy(anyString())).thenReturn(null); mailingService.signup(username); verify(userDB).createUser(new User(username)); }
  45. 45. COMMAND & QUERY SEPARATION REIHENFOLGE IMMER NÖOTWENDIG? public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); ... } else { ... } } @Test public void signup() throws Exception { ... when(userDB.findUserBy(anyString())).thenReturn(null); mailingService.signup(username); verify(userDB).createUser(new User(username)); }
  46. 46. COMMAND & QUERY SEPARATION REIHENFOLGE IMMER NÖOTWENDIG? public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); ... } else { ... } } @Test public void signup() throws Exception { ... when(userDB.findUserBy(anyString())).thenReturn(null); mailingService.signup(username); verify(userDB).createUser(new User(username)); }
  47. 47. COMMAND & QUERY SEPARATION REIHENFOLGE IMMER NÖOTWENDIG? public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); ... @Test public void signup() throws Exception { ... when(userDB.findUserBy(anyString())).thenReturn(null); mailingService.signup(username); verify(userDB).createUser(new User(username)); } „Allow Queries, expect Commands!“
  48. 48. LISTEN TO YOUR TESTS! Image by M.J. Moneymaker
  49. 49. LISTEN TO YOUR TESTS! # Verifications Image by M.J. Moneymaker
  50. 50. LISTEN TO YOUR TESTS! # Verifications Overspecification! Image by M.J. Moneymaker
  51. 51. LISTEN TO YOUR TESTS! # Verifications Overspecification! # Dependencies Image by M.J. Moneymaker
  52. 52. LISTEN TO YOUR TESTS! # Verifications Overspecification! # Dependencies Extract Class! Image by M.J. Moneymaker
  53. 53. LISTEN TO YOUR TESTS! # Verifications Overspecification! # Dependencies Extract Class! # Interactions Image by M.J. Moneymaker
  54. 54. LISTEN TO YOUR TESTS! # Verifications Overspecification! # Dependencies Extract Class! # Interactions Tell, don‘t ask! Image by M.J. Moneymaker
  55. 55. TELL DONT ASK => Tell don't ask public void volumeUpClicked() { int volume = speaker.getVolume(); if (volume < speaker.getMaximumVolume()) { speaker.setVolume(volume++); } }
  56. 56. TELL DONT ASK => Tell don't ask public void volumeUpClicked() { int volume = speaker.getVolume(); if (volume < speaker.getMaximumVolume()) { speaker.setVolume(volume++); } }
  57. 57. TELL DONT ASK => Tell don't ask public void volumeUpClicked() { int volume = speaker.getVolume(); if (volume < speaker.getMaximumVolume()) { speaker.setVolume(volume++); } } public void volumeUpClicked() { speaker.putUpVolume(); } class Speaker { public void putUpVolume() { if (this.volume < this.maximum this.volume++; } } ...
  58. 58. VERMEIDEN
  59. 59. SWEETSPOT
  60. 60. BEST PRACTICES
  61. 61. MOCKIST ODER CLASSICIST?
  62. 62. MOCKIST ODER CLASSICIST? TRADE-OFFS!
  63. 63. QUELLEN • „Growing Object Oriented Systems“, Nat Pryce, Steve Freeman • "Mocks Aren't Stubs", Martin Fowler • "Integration Operation Segregation Principle", Ralf Westphal • "Die kniffligen Fälle beim Testen - Sichtbarkeit", Stefan Lieser
  64. 64. Q&A ?!
  65. 65. Licence Creative Commons Attribution-ShareAlike 3.0

×