Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Object-Oriented JUnit Tests

342 views

Published on

JavaDay Minsk 2017; 3 June 2017; Minsk, Belarus; video is here: https://www.youtube.com/watch?v=1bAixLaOCSA

Published in: Technology

Object-Oriented JUnit Tests

  1. 1. /38@yegor256 1 Yegor Bugayenko Object-Oriented JUnit Tests
  2. 2. /38@yegor256 2 Why OOP?
  3. 3. /38@yegor256 3 yegor256/hangman 11 @funivan
  4. 4. /38@yegor256 4 Volume 2 $20 Free shipment
  5. 5. /38@yegor256 5 Unit testing anti-patterns: Happy Path Tests Validation and Boundary Easy Tests The Giant The Cuckoo The Conjoined Twins The Slow Poke Anal Probe Test It All Line Hitter Wait and See The Silent Catcher Chain Gang The Mockery The Free Ride The Local Hero Wet Floor The Flickering Test The Environmental Vandal Second Class Citizens The Secret Catcher Logic in Tests Code Matching Misleading Tests Not Asserting Asserting on Not-Null Forty Foot Pole Test With No Name Excessive Setup The Dead Tree The Turing Test The Mother Hen The Sleeper The Butterfly Doppelgänger The Inspector Structured Inspection The Cupcake
  6. 6. /38@yegor256 Dependencies 6 are evil Unbreakable
  7. 7. /38@yegor256 7 class Book { private int id; String title() { return Database.getInstance().fetch( “SELECT title FROM book WHERE id=?”,
 this.id ); } } String title = new Book().title();
  8. 8. /38@yegor256 8 Book BookTest DatabaseSomething
  9. 9. /38@yegor256 9 class Book { private int id; String title() { return DbUtils.fetch( “SELECT title FROM book WHERE id=?”,
 this.id ); } } static Johan Haleby
  10. 10. /38@yegor256 10 class Book { private int id; String title() { return Database.getInstance().fetch( “SELECT title FROM book WHERE id=?”,
 this.id ); } } global
  11. 11. /38@yegor256 11 class DbUtils { private static int port; static String fetch(String sql) { // .. } } class Database { private static Database INSTANCE; private int port; private Database() {} static Database getInstance() { if (Database.INSTANCE == null) { Database.INSTANCE = new Database(); } return Database.INSTANCE; } String fetch(String sql) { // .. } }
  12. 12. /38@yegor256 12 class DbUtils { private static int port; static String fetch(String sql) { // .. } } class Database { private static Database INSTANCE; private int port; private Database() {} static Database getInstance() { if (Database.INSTANCE == null) { Database.INSTANCE = new Database(); } return Database.INSTANCE; } static void setInstance(Database db) { Database.INSTANCE = db; } String fetch(String sql) { // .. } }
  13. 13. /38@yegor256 13 class Book { private int id; String title() { return new Database().fetch( “SELECT title FROM book WHERE id=?”,
 this.id ); } } new
  14. 14. /38@yegor256 14 class Book { private int id; private Database database; Book() { this(new Database()); } Book(Database db) { this.database = db; } String title() { return this.database.fetch( “SELECT title FROM book WHERE id=?”,
 this.id ); } } DependencyInjection
  15. 15. /38@yegor256 15 new Book(new NotRealDatabase()); class NotRealDatabase implements Database { // ... } interfaces @Override
  16. 16. /38@yegor256 16 static evil! singletons new interface-less
  17. 17. /38@yegor256 Mocking 17 is evil Ad hoc
  18. 18. /38@yegor256 18 static import org.mockito.Mockito.*; class BookTest { @Test public canFetchTitleFromDatabase() { Database db = mock(Database.class); doReturn(“UML Distilled”).when(db).fetch( “SELECT title FROM book WHERE id=?”, 123 ); Book book = new Book(db, 123); assert book.title().equals(“UML Distilled”); } }
  19. 19. /38@yegor256 19 mocking algorithm
  20. 20. /38@yegor256 20 Book BookTest db assumptions
  21. 21. /38@yegor256 21 Safety net. (c) By John M, CC BY-SA 2.0
  22. 22. /38@yegor256 22 static import org.mockito.Mockito.*; class BookTest { @Test public canFetchTitleFromDatabase() { Database db = mock(Database.class); doReturn(“UML Distilled”).when(db).fetch( “SELECT title FROM book WHERE id=?”, 123 ); Book book = new Book(db, 123); assert book.title().equals(“UML Distilled”); } } class Book { private int id; private Database database; Book(Database db, int i) { this.database = db; this.id = i; } String title() { return this.database.fetch( “SELECT title FROM book WHERE id=?”,
 this.id ); } }
  23. 23. /38@yegor256 23 False positives.
  24. 24. /38@yegor256 24 Fakes or doubles.
  25. 25. /38@yegor256 25 class BookTest { @Test public canFetchTitleFromDatabase() { Book book = new Book( new FakeDatabase(), 123 ); assert book.title().equals(“UML Distilled”); } } class Book { private int id; private Database database; Book(Database db, int i) { this.database = db; this.id = i; } String title() { return this.database.fetch( “SELECT title FROM book WHERE id=?”,
 this.id ); } }
  26. 26. /38@yegor256 26 class BookTest { @Test public canFetchTitleFromDatabase() { Book book = new Book( new FakeDatabase() .withTitle(123, “UML Distilled”) .withTitle(1, “Elegant Objects”) .withUser(“Peter Pan”), 123 ); assert book.title().equals(“UML Distilled”); } }
  27. 27. /38@yegor256 27 Ad hoc mocking. Fakes.
  28. 28. /38@yegor256 Algorithms 28 are evil In-method Maybe!
  29. 29. /38@yegor256 29 cactoos www.cactoos.org
  30. 30. /38@yegor256 30 class BookTest { @Test public canBuildURL() { Book book = new Book(); book.setLanguage(Locale.RUSSIAN); book.setEncoding(“UTF-8”); book.setTitle(“Дон Кихот”); assert book.getURL().contains(“%D0%94%”); } } procedural!
  31. 31. /38@yegor256 31 Hamcrest An anagram for “matchers”.
  32. 32. /38@yegor256 32 A test method must have nothing but a single statement: assertThat()
  33. 33. /38@yegor256 33 assertThat(book, hasTitle(“UML Distilled”)); “We assert that the book behaves as if it has a title.”
  34. 34. /38@yegor256 34 assertThat( book, hasURL( hasPath( containsString( equalTo(“%D0%94%”) ) ) ) ); We assert that
 the book behaves as if it has a URL that behaves as if it has a path that behaves as if it contains a string that behaves as if it is equal to “%D0%94%”.
  35. 35. /38@yegor256 35
  36. 36. /38@yegor256 36
  37. 37. /38@yegor256 37 shorter test methods why?! immutable objects share matchers
  38. 38. /38@yegor256 38 Quality Award. $4096

×