Wann soll ich mocken?

65
Wann soll ich mocken? XP Days Germany David Völkel 21.11.2016

Transcript of Wann soll ich mocken?

Page 1: Wann soll ich mocken?

Wann soll ich mocken?

XP Days Germany

David Völkel

21.11.2016

Page 2: Wann soll ich mocken?

@davidvoelkel

@softwerkskammer

@codecentric

TDD & Design

Page 3: Wann soll ich mocken?

SCHICHTEN TESTEN?

Page 4: Wann soll ich mocken?

INTEGRIERTER TEST

Page 5: Wann soll ich mocken?

Unittest

Mock

MOCKING

Page 6: Wann soll ich mocken?

Unittest

Mock

MOCKING

Page 7: Wann soll ich mocken?

Unittest

Mock

MOCKING

Page 8: Wann soll ich mocken?

aufwendiges Setup

Fehlerfindung

# Testfällen

Langsames Feedback

Refactorability sinkt

Isolationsaufwand

Zu wenig Nutzen

Lesbarkeit

TRADE-OFF

ZU GROSS vs ZU KLEIN

Page 9: Wann soll ich mocken?

Woran

orientieren

?

Page 10: Wann soll ich mocken?

IDEOLOGIEN MOCKISTS CLASSICISTS

"Mocks Aren't Stubs", Martin Fowler

Page 11: Wann soll ich mocken?

TRADE-OFFS

statt

IDEOLOGIEN!

Page 12: Wann soll ich mocken?

USE CASES

MOCKISTS CLASSICISTS

Anbindung Drittsysteme

Page 13: Wann soll ich mocken?

USE CASES

MOCKISTS CLASSICISTS

Anbindung Drittsysteme

Bedingte Interaktionen

Page 14: Wann soll ich mocken?

USE CASES

MOCKISTS CLASSICISTS

SWEETSPOT

Anbindung Drittsysteme

Bedingte Interaktionen

Page 15: Wann soll ich mocken?

USE CASES

MOCKISTS CLASSICISTS

SWEETSPOT

Anbindung Drittsysteme

Bedingte Interaktionen

Geringer

Nutzen

Page 16: Wann soll ich mocken?

VERMEIDEN

USE CASES

MOCKISTS CLASSICISTS

SWEETSPOT

Anbindung Drittsysteme

Bedingte Interaktionen

Geringer

Nutzen

Page 17: Wann soll ich mocken?

VERMEIDEN

MOCKING

SWEETSPOT

„BEST PRACTICES“

Page 18: Wann soll ich mocken?

VERMEIDEN

Page 19: Wann soll ich mocken?

„DONT MOCK VALUES!

Page 20: Wann soll ich mocken?

„DON‘T MOCK VALUES!

new Value()

Page 21: Wann soll ich mocken?

„DON‘T MOCK VALUES!

new Value()

TestDataBuilderForValue

.withDefaults()

.withField(“1“)

Page 23: Wann soll ich mocken?

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() + ",\n\n" + "We have a special offer for you.\n\n" + "Best regards,\n" + "ACME Customer Service"; mailService.sendMail(email, content);

}

Page 24: Wann soll ich mocken?

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() + ",\n\n" + "We have a special offer for you.\n\n" + "Best regards,\n" + "ACME Customer Service"; mailService.sendMail(email, content);

}

INTEGRATION OPERATION

SEGREGATION PRINCIPLE

Page 25: Wann soll ich mocken?

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() + ",\n\n" + "We have a special offer for you.\n\n" + "Best regards,\n" + "ACME Customer Service"; mailService.sendMail(email, content);

}

INTEGRATION OPERATION

SEGREGATION PRINCIPLE

Page 26: Wann soll ich mocken?

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() + ",\n\n" + "We have a special offer for you.\n\n" + "Best regards,\n" + "ACME Customer Service";

}

INTEGRATION OPERATION

SEGREGATION PRINCIPLE

Page 27: Wann soll ich mocken?

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() + ",\n\n" + "We have a special offer for you.\n\n" + "Best regards,\n" + "ACME Customer Service";

}

TESTS?

N Unittests

Page 28: Wann soll ich mocken?

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() + ",\n\n" + "We have a special offer for you.\n\n" + "Best regards,\n" + "ACME Customer Service";

}

TESTS? 1 Integrierter Test

N Unittests

Page 30: Wann soll ich mocken?

PUSH LOGIC

DOWN THE STACK

Page 31: Wann soll ich mocken?

SWEETSPOT

Page 32: Wann soll ich mocken?

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

Page 33: Wann soll ich mocken?

SYSTEM GRENZEN

3rd Party

Service

Adapter

Page 34: Wann soll ich mocken?

SYSTEM GRENZEN

3rd Party

Service

Mock

Page 35: Wann soll ich mocken?

OUTSIDE-IN

DESIGN

Page 36: Wann soll ich mocken?

OUTSIDE-IN

DESIGN

Alternative “Fake it“

Page 37: Wann soll ich mocken?

BEST

PRACTICES

Page 38: Wann soll ich mocken?

NO

OVERSPECIFICATION!

Page 39: Wann soll ich mocken?

NO

OVERSPECIFICATION!

“Specify exactly what should happen but no more”

Page 40: Wann soll ich mocken?

REIHENFOLGE?

Page 41: Wann soll ich mocken?

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 { ...

} }

Page 42: Wann soll ich mocken?

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 { ...

} }

Page 43: Wann soll ich mocken?

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 { ...

} }

Page 44: Wann soll ich mocken?

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));

}

Page 45: Wann soll ich mocken?

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));

}

Page 46: Wann soll ich mocken?

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));

}

Page 47: Wann soll ich mocken?

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!“

Page 51: Wann soll ich mocken?

LISTEN TO YOUR TESTS!

# Verifications

Overspecification!

# Dependencies

Image by M.J. Moneymaker

Page 52: Wann soll ich mocken?

LISTEN TO YOUR TESTS!

# Verifications

Overspecification!

# Dependencies

Extract Class!

Image by M.J. Moneymaker

Page 53: Wann soll ich mocken?

LISTEN TO YOUR TESTS!

# Verifications

Overspecification!

# Dependencies

Extract Class!

# Interactions

Image by M.J. Moneymaker

Page 54: Wann soll ich mocken?

LISTEN TO YOUR TESTS!

# Verifications

Overspecification!

# Dependencies

Extract Class!

# Interactions

Tell, don‘t ask!

Image by M.J. Moneymaker

Page 55: Wann soll ich mocken?

TELL DONT ASK

=> Tell don't ask

public void volumeUpClicked() { int volume = speaker.getVolume(); if (volume < speaker.getMaximumVolume()) { speaker.setVolume(volume++); }

}

Page 56: Wann soll ich mocken?

TELL DONT ASK

=> Tell don't ask

public void volumeUpClicked() { int volume = speaker.getVolume(); if (volume < speaker.getMaximumVolume()) { speaker.setVolume(volume++); }

}

Page 57: Wann soll ich mocken?

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.maximumVolume) {

this.volume++; }

} ...

Page 58: Wann soll ich mocken?

VERMEIDEN

Page 59: Wann soll ich mocken?

SWEETSPOT

Page 60: Wann soll ich mocken?

BEST

PRACTICES

Page 61: Wann soll ich mocken?

MOCKIST

ODER

CLASSICIST?

Page 62: Wann soll ich mocken?

MOCKIST

ODER

CLASSICIST?

TRADE-OFFS!

Page 63: Wann soll ich mocken?

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

Page 64: Wann soll ich mocken?

Q&A ?!