Wann soll ich mocken?
XP Days Germany
David Völkel
21.11.2016
@davidvoelkel
@softwerkskammer
@codecentric
TDD & Design
SCHICHTEN TESTEN?
INTEGRIERTER TEST
Unittest
Mock
MOCKING
Unittest
Mock
MOCKING
Unittest
Mock
MOCKING
aufwendiges Setup
Fehlerfindung
# Testfällen
Langsames Feedback
Refactorability sinkt
Isolationsaufwand
Zu wenig Nutzen
Le...
Woran
orientieren
?
IDEOLOGIEN
MOCKISTS CLASSICISTS
"Mocks Aren't Stubs", Martin Fowler
TRADE-OFFS
statt
IDEOLOGIEN!
USE CASES
MOCKISTS CLASSICISTS
Anbindung Drittsysteme
USE CASES
MOCKISTS CLASSICISTS
Anbindung Drittsysteme
Bedingte
Interaktionen
USE CASES
MOCKISTS CLASSICISTS
SWEETSPOT
Anbindung Drittsysteme
Bedingte
Interaktionen
USE CASES
MOCKISTS CLASSICISTS
SWEETSPOT
Anbindung Drittsysteme
Bedingte
Interaktionen
Geringer
Nutzen
VERMEIDEN
USE CASES
MOCKISTS CLASSICISTS
SWEETSPOT
Anbindung Drittsysteme
Bedingte
Interaktionen
Geringer
Nutzen
VERMEIDEN
MOCKING
SWEETSPOT
„BEST PRACTICES“
VERMEIDEN
„DONT MOCK VALUES!
„DON‘T MOCK VALUES!
new Value()
„DON‘T MOCK VALUES!
new Value()
TestDataBuilderForValue
.withDefaults()
.withField(“1“)
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
"Integration Operation Segregation Principle", Ralf Westphal
"Die kniffligen F...
INTEGRATION OPERATION
SEGREGATION PRINCIPLE
public void sendMailingTo(String email) {
Customer customer = customerDB.findC...
public void sendMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String title = customer.ge...
public void sendMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String title = customer.ge...
public void sendMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String content = renderCon...
public void sendMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String content = renderCon...
public void sendMailingTo(String email) {
Customer customer = customerDB.findCustomerBy(email);
String content = renderCon...
PUSH LOGIC
DOWN THE STACK
Siehe "The Failures of “Intro to TDD”" - Justin Searls
PUSH LOGIC
DOWN THE STACK
SWEETSPOT
public String signup(String username) throws Exception {
if(userDB.findUserBy(username) == null) {
userDB.createUser(new U...
SYSTEM GRENZEN
3rd
Party
Service
Adapter
SYSTEM GRENZEN
3rd
Party
Service
Mock
OUTSIDE-IN
DESIGN
OUTSIDE-IN
DESIGN
Alternative “Fake it“
BEST
PRACTICES
NO
OVERSPECIFICATION!
NO
OVERSPECIFICATION!
“Specify exactly what should happen
but no more”
REIHENFOLGE?
COMMAND & QUERY
SEPARATION
REIHENFOLGE
IMMER NÖOTWENDIG?
public String signup(String username) throws Exception {
if(userD...
COMMAND & QUERY
SEPARATION
REIHENFOLGE
IMMER NÖOTWENDIG?
public String signup(String username) throws Exception {
if(userD...
COMMAND & QUERY
SEPARATION
REIHENFOLGE
IMMER NÖOTWENDIG?
public String signup(String username) throws Exception {
if(userD...
COMMAND & QUERY
SEPARATION
REIHENFOLGE
IMMER NÖOTWENDIG?
public String signup(String username) throws Exception {
if(userD...
COMMAND & QUERY
SEPARATION
REIHENFOLGE
IMMER NÖOTWENDIG?
public String signup(String username) throws Exception {
if(userD...
COMMAND & QUERY
SEPARATION
REIHENFOLGE
IMMER NÖOTWENDIG?
public String signup(String username) throws Exception {
if(userD...
COMMAND & QUERY
SEPARATION
REIHENFOLGE
IMMER NÖOTWENDIG?
public String signup(String username) throws Exception {
if(userD...
LISTEN TO YOUR TESTS!
Image by M.J. Moneymaker
LISTEN TO YOUR TESTS!
# Verifications
Image by M.J. Moneymaker
LISTEN TO YOUR TESTS!
# Verifications
Overspecification!
Image by M.J. Moneymaker
LISTEN TO YOUR TESTS!
# Verifications
Overspecification!
# Dependencies
Image by M.J. Moneymaker
LISTEN TO YOUR TESTS!
# Verifications
Overspecification!
# Dependencies
Extract Class!
Image by M.J. Moneymaker
LISTEN TO YOUR TESTS!
# Verifications
Overspecification!
# Dependencies
Extract Class!
# Interactions
Image by M.J. Moneym...
LISTEN TO YOUR TESTS!
# Verifications
Overspecification!
# Dependencies
Extract Class!
# Interactions
Tell, don‘t ask!
Ima...
TELL DONT ASK
=> Tell don't ask
public void volumeUpClicked() {
int volume = speaker.getVolume();
if (volume < speaker.get...
TELL DONT ASK
=> Tell don't ask
public void volumeUpClicked() {
int volume = speaker.getVolume();
if (volume < speaker.get...
TELL DONT ASK
=> Tell don't ask
public void volumeUpClicked() {
int volume = speaker.getVolume();
if (volume < speaker.get...
VERMEIDEN
SWEETSPOT
BEST
PRACTICES
MOCKIST
ODER
CLASSICIST?
MOCKIST
ODER
CLASSICIST?
TRADE-OFFS!
QUELLEN
• „Growing Object Oriented Systems“,
Nat Pryce, Steve Freeman
• "Mocks Aren't Stubs",
Martin Fowler
• "Integration...
Q&A ?!
Licence
Creative Commons
Attribution-ShareAlike 3.0
Nächste SlideShare
Wird geladen in …5
×

Wann soll ich mocken?

238 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
0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

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

Keine Downloads
Aufrufe
Aufrufe insgesamt
238
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
10
Aktionen
Geteilt
0
Downloads
4
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

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

×