built-in fake objects

30
/29 @yegor256 1 Built-in Fake Objects Yegor Bugayenko

Upload: yegor-bugayenko

Post on 16-Jan-2017

257 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Built-in Fake Objects

/29@yegor256 1

Built-in Fake Objects

Yegor Bugayenko

Page 2: Built-in Fake Objects

/29@yegor256 2

“Mock objects are simulated objects that mimic the behavior of

real objects in controlled ways”

Page 3: Built-in Fake Objects

/29@yegor256 3

FakeObjects

Mocking Frameworks

Page 4: Built-in Fake Objects

/29@yegor256 4

static String report(User user) { return String.format( “Balance of %s is %d USD”, user.profile().name(), user.account().balance().usd() ); }

Page 5: Built-in Fake Objects

/29@yegor256 5

interface Profile { String name(); }

interface User { Profile profile(); Account account(); }

interface Account { Balance balance(); }

interface Balance { int usd(); }

Page 6: Built-in Fake Objects

/29@yegor256 6

@Test void printsReport() { User user = mock(User.class); assertThat( Foo.report(user), containsString(“Balance of”) ); }

Mockito

Page 7: Built-in Fake Objects

/29@yegor256 7@Test void printsReport() { Profile profile = mock(Profile.class); Account account = mock(Account.class); doReturn(“Jeffrey”).when(account).name(); Balance balance = mock(Balance.class); doReturn(123).when(balance).usd(); doReturn(balance).when(account).balance(); User user = mock(User.class); doReturn(profile).when(user).profile(); doReturn(account).when(user).account(); assertThat( Foo.report(user), containsString(“Balance of Jeffrey is 123 USD”) ); }

Page 8: Built-in Fake Objects

/29@yegor256 8

1. verbosity

Page 9: Built-in Fake Objects

/29@yegor256 9

@Test void printsReport() { Profile profile = mock(Profile.class); Account account = mock(Account.class); doReturn(“Jeffrey”).when(account).name(); Balance balance = mock(Balance.class); doReturn(123).when(balance).usd(); doReturn(balance).when(account).balance(); User user = mock(User.class); doReturn(profile).when(user).profile(); doReturn(account).when(user).account(); assertThat( Foo.report(user), containsString(“Balance of Jeffrey is 123 USD”) ); }

String report(User user) { return String.format( “Balance of %s is %d USD”, user.profile().name(), user.account().balance().usd() ); }

Page 10: Built-in Fake Objects

/29@yegor256 10

2. code duplication

Page 11: Built-in Fake Objects

/29@yegor256 11

@Test void reportIncludesUserName() { Profile profile = mock(Profile.class); Account account = mock(Account.class); doReturn(“Jeffrey”).when(account).name(); Balance balance = mock(Balance.class); doReturn(balance).when(account).balance(); User user = mock(User.class); doReturn(profile).when(user).profile(); doReturn(account).when(user).account(); assertThat( Foo.report(user), containsString(“Jeffrey”) ); }

@Test void reportIncludesBalanceInUSD() { Profile profile = mock(Profile.class); Account account = mock(Account.class); Balance balance = mock(Balance.class); doReturn(123).when(balance).usd(); doReturn(balance).when(account).balance(); User user = mock(User.class); doReturn(profile).when(user).profile(); doReturn(account).when(user).account(); assertThat( Foo.report(user), containsString(“123 USD”) ); }

Page 12: Built-in Fake Objects

/29@yegor256 12

3. complexity

Page 13: Built-in Fake Objects

/29@yegor256 13

example!!

Page 14: Built-in Fake Objects

/29@yegor256 14

4. fragility

because

of coupl

ing

Page 15: Built-in Fake Objects

/29@yegor256 15

@Test void printsReport() { Profile profile = mock(Profile.class); Account account = mock(Account.class); doReturn(“Jeffrey”).when(account).name(); Balance balance = mock(Balance.class); doReturn(123).when(balance).usd(); doReturn(balance).when(account).balance(); User user = mock(User.class); doReturn(profile).when(user).profile(); doReturn(account).when(user).account(); assertThat( Foo.report(user), containsString(“Balance of Jeffrey is 123 USD”) ); }

String report(User user) { return String.format( “Balance of %s is %d USD”, user.profile().name(), user.account().balance().usd() ); }

Page 16: Built-in Fake Objects

/29@yegor256 16

@Test void printsReport() { Profile profile = mock(Profile.class); Account account = mock(Account.class); doReturn(“Jeffrey”).when(account).name(); Balance balance = mock(Balance.class); doReturn(123).when(balance).usd(); doReturn(balance).when(account).balance(); User user = mock(User.class); doReturn(profile).when(user).profile(); doReturn(account).when(user).account(); assertThat( Foo.report(user), containsString(“Balance of Jeffrey is 123 USD”) ); }

String report(User user) { return String.format( “Balance of %s is %d USD”, user.profile().name(), user.account().usd() ); }

Page 17: Built-in Fake Objects

/29@yegor256 17

“Unit tests are your safety net”

Page 18: Built-in Fake Objects

/29@yegor256 18

false positive

Page 19: Built-in Fake Objects

/29@yegor256 19

throw-away tests

Page 20: Built-in Fake Objects

/29@yegor256 20

a solution?fake objects!

Page 21: Built-in Fake Objects

/29@yegor256 21

interface User { Profile profile(); Account account(); class Fake { Fake(String name, int balance) { // ... } // ... } }

Page 22: Built-in Fake Objects

/29@yegor256 22

@Test void printsReport() { User user = new User.Fake(“Jeffrey”, 123); assertThat( Foo.report(user), containsString(“Balance of Jeffrey is 123 USD”) ); }

verbosity?

Page 23: Built-in Fake Objects

/29@yegor256 23

@Test void reportIncludesUserName() { User user = new User.Fake(“Jeffrey”); assertThat( Foo.report(user), containsString(“Jeffrey”) ); }

code duplication?

@Test void reportIncludesBalanceInUSD() { User user = new User.Fake(123); assertThat( Foo.report(user), containsString(“123 USD”) ); }

Page 24: Built-in Fake Objects

/29@yegor256 24

@Test void reportIncludesUserName() { User user = new User.Fake(“Jeffrey”); assertThat( Foo.report(user), containsString(“Jeffrey”) ); }

complexity?

@Test void reportIncludesBalanceInUSD() { User user = new User.Fake(123); assertThat( Foo.report(user), containsString(“123 USD”) ); }

Page 25: Built-in Fake Objects

/29@yegor256 25

String report(User user) { return String.format( “Balance of %s is %d USD”, user.profile().name(), user.account().balance().usd() ); }

fragility?

@Test void reportIncludesBalanceInUSD() { User user = new User.Fake(123); assertThat( Foo.report(user), containsString(“123 USD”) ); }

Page 26: Built-in Fake Objects

/29@yegor256 26

no throw-away tests any more

Page 27: Built-in Fake Objects

/29@yegor256 27

always ship themtogether!

Page 28: Built-in Fake Objects

/29@yegor256 28

interface User { Profile profile(); Account account(); class Fake { } }

class UserTest { @Test void hasBalance() { User user = new User.Fake(123); assertThat( user.account().balance().usd(), not(equalTo(0)) ); } }

Page 29: Built-in Fake Objects

/29@yegor256 29

FakeObjects

Mocking Frameworks

Page 30: Built-in Fake Objects

/29@yegor256 30

Section 2.8

Don’t mock; use fakes