Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Test unitaire ? Mock ? TDD ? Kezako ? (En finir...

David
January 17, 2013

Test unitaire ? Mock ? TDD ? Kezako ? (En finir avec les régressions)

Vous subissez les régressions à chaque livraison ? Vous ne voyez pas l’intérêt des tests unitaires car ils ne servent qu’à tester des additions ? Si c’est le cas, suivez David dans la quête du Test Driven Development. Nous rencontrerons pléthore d'ennemies contre lesquels nous aurons à combattre : bugs, complexité, code statique, couplage fort. Ils essaieront de nous barrer la route, mais heureusement, nous pourrons compter sur nos alliés jUnit, Mockito, refactoring et injection/dépendance.

David

January 17, 2013
Tweet

More Decks by David

Other Decks in Programming

Transcript

  1. Test unitaire ? Mock ? TDD ? Kezako ? en

    finir avec les régressions par David Wursteisen 17 JANVIER 2013
  2. La documentation explique le code /** * * @param xml

    : document xml représentant le swap * @return objet Swap */ public Swap parse(String xml) { Swap swap = new Swap(); String currency = getNodeValue("/swap/currency", xml); swap.setCurrency(currency); /* beaucoup de code... */ Date d = new Date(); if(test == 1) { if(d.after(spotDate)) { swap.setType("IRS"); } else { swap.setType("CURVE"); } } else if (test == 2) { if(d.after(spotDate)) { swap.setType("IRS"); } else { swap.setType("CURVE"); } } /* encore beaucoup de code... */ return swap; }
  3. La documentation explique le code 1 /** 2 * 3

    * @param xml : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency); [...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } [...] /* encore beaucoup de code... */ 1135 return swap; 1136 } 1000 LIGNES !
  4. La documentation a raison 1 /** 2 * Always returns

    true. 3 */ 4 public boolean isAvailable() { 5 return false; 6 }
  5. La documentation a raison 1 /** 2 * Always returns

    true. 3 */ 4 public boolean isAvailable() { 5 return false; 6 } WTF ?!?
  6. 4 obj = networkService.getObject("product", id); 1 public Object getProduct(String id)

    { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } Faire du code qui marche
  7. 4 obj = networkService.getObject("product", id); 1 public Object getProduct(String id)

    { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } Faire du code qui marche
  8. 1 public Object getProduct(String id) { 2 Object obj =

    null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } 2 Object obj = null; 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } Faire du code qui marche NullPointerException !
  9. 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 1 public void

    affiche(BankAccount account, ProductService service) { 2 System.out.println("Bank Account : "+this.name); 3 System.out.println("Autres informations : "); 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 6 System.out.println(account); 7 System.out.println("=== FIN ==="); 8 9 } Code simple HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  10. 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 1 public void

    affiche(BankAccount account, ProductService service) { 2 System.out.println("Bank Account : "+this.name); 3 System.out.println("Autres informations : "); 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 6 System.out.println(account); 7 System.out.println("=== FIN ==="); 8 9 } Code simple HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  11. 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 1 public void

    affiche(BankAccount account, ProductService service) { 2 System.out.println("Bank Account : "+this.name); 3 System.out.println("Autres informations : "); 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 6 System.out.println(account); 7 System.out.println("=== FIN ==="); 8 9 } Code simple HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  12. 1 @Test 2 public void can_deposit() { 3 bankAccount.setBalance(50); 4

    5 boolean result = bankAccount.deposit(1000); 6 7 assertTrue(result); 8 assertEquals(1050, bankAccount.getBalance()); 9 } 3 bankAccount.setBalance(50); Test d’abord !
  13. 1 @Test 2 public void can_deposit() { 3 bankAccount.setBalance(50); 4

    5 boolean result = bankAccount.deposit(1000); 6 7 assertTrue(result); 8 assertEquals(1050, bankAccount.getBalance()); 9 } 3 bankAccount.setBalance(50); Test d’abord !
  14. 5 boolean result = bankAccount.deposit(1000); 1 @Test 2 public void

    can_deposit() { 3 bankAccount.setBalance(50); 4 5 boolean result = bankAccount.deposit(1000); 6 7 assertTrue(result); 8 assertEquals(1050, bankAccount.getBalance()); 9 } Test d’abord !
  15. 1 @Test 2 public void can_deposit() { 3 bankAccount.setBalance(50); 4

    5 boolean result = bankAccount.deposit(1000); 6 7 assertTrue(result); 8 assertEquals(1050, bankAccount.getBalance()); 9 } Test d’abord ! 7 assertTrue(result); 8 assertEquals(1050, bankAccount.getBalance());
  16. Test d’abord ! 1 boolean deposit(int amount) { 2 bal

    = bal + amount; 3 return true; 4 }
  17. Test d’abord ! 1 boolean deposit(int amount) { 2 bal

    = bal + amount; 3 return true; 4 }
  18. Test d’abord ! 1 @Test 2 public void cant_deposit_with_negative_amount() {

    3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 }
  19. Test d’abord ! 1 @Test 2 public void cant_deposit_with_negative_amount() {

    3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 } 3 bankAccount.setBalance(100);
  20. Test d’abord ! 1 @Test 2 public void cant_deposit_with_negative_amount() {

    3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 } 5 boolean result = bankAccount.deposit(-20);
  21. Test d’abord ! 1 @Test 2 public void cant_deposit_with_negative_amount() {

    3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 } 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance());
  22. Test d’abord ! 1 boolean deposit(int amount) { 2 bal

    = bal + amount; 3 return true; 4 }
  23. Test d’abord ! 1 boolean deposit(int amount) { 2 bal

    = bal + amount; 3 return true; 4 }
  24. Test d’abord ! 1 boolean deposit(int amount) { 2 if(amount

    < 0) { 3 return false; 4 } 5 bal = bal + amount; 6 return true; 7 }
  25. Test d’abord ! 1 boolean deposit(int amount) { 2 if(amount

    < 0) { 3 return false; 4 } 5 bal = bal + amount; 6 return true; 7 }
  26. les «3 A» : Acteur/Action/Assertion 1 @Test 2 public void

    cant_deposit_with_negative_amount() { 3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 }
  27. 1 @Test 2 public void cant_deposit_with_negative_amount() { 3 bankAccount.setBalance(100); 4

    5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 } les «3 A» : Acteur/Action/Assertion 3 bankAccount.setBalance(100); Acteur
  28. 1 @Test 2 public void cant_deposit_with_negative_amount() { 3 bankAccount.setBalance(100); 4

    5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 } les «3 A» : Acteur/Action/Assertion 5 boolean result = bankAccount.deposit(-20); Action
  29. 1 @Test 2 public void cant_deposit_with_negative_amount() { 3 bankAccount.setBalance(100); 4

    5 boolean result = bankAccount.deposit(-20); 6 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 } les «3 A» : Acteur/Action/Assertion 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); Assertions
  30. 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10

    Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 13 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); 32 }
  31. 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10

    Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 13 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); 32 }
  32. 1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("=======

    testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 13 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); 32 } 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); BRUIT
  33. KISS ! 1 @Test 2 public void can_get_customer() throws Exception

    { 3 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 4 Assert.assertEquals("Les accountId doivent être identiques.", 5 "ABC99", targetDTO.getAccountId()); 6 }
  34. nouveau bug = nouveau test 1 public Object getProduct(String id)

    { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 }
  35. 1 public Object getProduct(String id) { 2 Object obj =

    null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } nouveau bug = nouveau test 6 System.err.println("Error with obj : " + obj.toString()); LE BUG EST ICI !
  36. nouveau bug = nouveau test 1 @Test 2 public void

    can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 }
  37. 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3

    Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 } nouveau bug = nouveau test 3 Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty");
  38. 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3

    Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 } nouveau bug = nouveau test 6 Object product = service.getProduct("azerty");
  39. 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3

    Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 } nouveau bug = nouveau test 8 assertThat(product).isNull();
  40. nouveau bug = nouveau test 1 public Object getProduct(String id)

    { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 }
  41. nouveau bug = nouveau test 1 public Object getProduct(String id)

    { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 }
  42. 1 public Object getProduct(String id) { 2 Object obj =

    null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } nouveau bug = nouveau test 6 System.err.println("Error with obj : " + obj.toString()); LE BUG EST TOUJOURS ICI !
  43. 1 public Object getProduct(String id) { 2 Object obj =

    null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj with id: " + id); 7 } 8 return obj; 9 } nouveau bug = nouveau test 6 System.err.println("Error with obj with id: " + id);
  44. nouveau bug = nouveau test 1 public Object getProduct(String id)

    { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj with id: " + id); 7 } 8 return obj; 9 } 6 System.err.println("Error with obj with id: " + id);
  45. code complexe 1 /** 2 * 3 * @param xml

    : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency); [...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } [...] /* encore beaucoup de code... */ 1135 return swap; 1136 }
  46. 1 @Test 2 public void can_parse_xml() throws Exception { 3

    String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 4 "<!--\n" + 5 "\t== Copyright (c) 2002-2005. All rights reserved.\n" + 6 "\t== Financial Products Markup Language is subject to the FpML public license.\n" + 7 "\t== A copy of this license is available at http://www.fpml.org/documents/license\n" + 8 "-->\n" + 9 "<FpML version=\"4-2\" xmlns=\"http://www.fpml.org/2005/FpML-4-2\" xmlns:xsi=\"http://www.w3.org/2001/ XMLSchema-instance\" xsi:schemaLocation=\"http://www.fpml.org/2005/FpML-4-2 fpml-main-4-2.xsd\" xsi:type= \"TradeCashflowsAsserted\">\n" + 10 "\t<header>\n" + 11 "\t\t<messageId messageIdScheme=\"http://www.example.com/messageId\">CEN/2004/01/05/15-38</messageId>\n" + 12 "\t\t<sentBy>ABC</sentBy>\n" + 13 "\t\t<sendTo>DEF</sendTo>\n" + 14 "\t\t<creationTimestamp>2005-01-05T15:38:00-00:00</creationTimestamp>\n" + 15 "\t</header>\n" + 16 "\t<asOfDate>2005-01-05T15:00:00-00:00</asOfDate>\n" + 17 "\t<tradeIdentifyingItems>\n" + 18 "\t\t<partyTradeIdentifier>\n" + 19 "\t\t\t<partyReference href=\"abc\"/>\n" + 20 "\t\t\t<tradeId tradeIdScheme=\"http://www.abc.com/tradeId/\">trade1abcxxx</tradeId>\n" + 21 "\t\t</partyTradeIdentifier>\n" + 22 "\t\t<partyTradeIdentifier>\n" + 23 "\t\t\t<partyReference href=\"def\"/>\n" + 24 "\t\t\t<tradeId tradeIdScheme=\"http://www.def.com/tradeId/\">123cds</tradeId>\n" + 25 "\t\t</partyTradeIdentifier>\n" + 26 "\t</tradeIdentifyingItems>\n" + 27 "\t<adjustedPaymentDate>2005-01-31</adjustedPaymentDate>\n" + 28 "\t<netPayment>\n" + 29 "\t\t<identifier netPaymentIdScheme=\"http://www.centralservice.com/netPaymentId\">netPaymentABCDEF001</ identifier>\n" + 30 "\t\t<payerPartyReference href=\"abc\"/>\n" + 31 "\t\t<receiverPartyReference href=\"def\"/>\n" + 32 "\t\t<paymentAmount>\n" +
  47. code complexe 1 /** 2 * 3 * @param xml

    : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency); [...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } [...] /* encore beaucoup de code... */ 1135 return swap; 1136 }
  48. 1 /** 2 * 3 * @param xml : document

    xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency); [...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } [...] /* encore beaucoup de code... */ 1135 return swap; 1136 } code complexe 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } EXTRACT METHOD !
  49. code complexe 1 public void updateSwapType(Swap swapToUpdate, Date now, Date

    spotDate, int test) { 2 if(test == 1) { 3 if(now.after(spotDate)) { 4 swapToUpdate.setType("IRS"); 5 } else { 6 swapToUpdate.setType("CURVE"); 7 } 8 } else if (test == 2) { 9 if(now.after(spotDate)) { 10 swapToUpdate.setType("IRS"); 11 } else { 12 swapToUpdate.setType("CURVE"); 13 } 14 } 15 }
  50. code complexe 1 @Test 2 public void can_update_swap_type() throws Exception

    { 3 Swap swap = new Swap(); 4 Date now = simpleDateFormat.parse("2012-06-15"); 5 Date before = simpleDateFormat.parse("2012-05-05"); 6 service.updateSwapType(swap, now, before, 1); 7 assertEquals("IRS", swap.getType()); 8 }
  51. Singleton 1 public class ProductService { 2 3 private static

    ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance(); 10 } 11 12 public static ProductService getInstance() { 13 return instance; 14 } 15 16 17 18 public Object getProduct(String id) { 19 return daoService.getObject("product", id); 20 } 21 }
  52. 1 public class ProductService { 2 3 private static ProductService

    instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance(); 10 } 11 12 public static ProductService getInstance() { 13 return instance; 14 } 15 16 17 18 public Object getProduct(String id) { 19 return daoService.getObject("product", id); 20 } 21 } Singleton 3 private static ProductService instance = new ProductService();
  53. 1 public class ProductService { 2 3 private static ProductService

    instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance(); 10 } 11 12 public static ProductService getInstance() { 13 return instance; 14 } 15 16 17 18 public Object getProduct(String id) { 19 return daoService.getObject("product", id); 20 } 21 } Singleton 7 private ProductService() { 9 daoService = DAOService.getInstance(); 10 }
  54. Singleton 1 public class ProductService { 2 3 private static

    ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance(); 10 } 11 12 public static ProductService getInstance() { 13 return instance; 14 } 15 16 17 18 public Object getProduct(String id) { 19 return daoService.getObject("product", id); 20 } 21 }
  55. Singleton 1 public void validateSwap(String id) { 2 Swap swap

    = (Swap) ProductService.getInstance().getProduct(id); 3 swap.updateState("VALIDATE"); 4 ProductService.getInstance().save(swap); 5 }
  56. 1 public void validateSwap(String id) { 2 Swap swap =

    (Swap) ProductService.getInstance().getProduct(id); 3 swap.updateState("VALIDATE"); 4 ProductService.getInstance().save(swap); 5 } Singleton ProductService.getInstance() 4 ProductService.getInstance() COUPLAGE FORT
  57. Injection 1 private ProductService productService; 2 3 public void setProductService(ProductService

    injectedService) { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE"); 10 productService.save(swap); 11 }
  58. 1 private ProductService productService; 2 3 public void setProductService(ProductService injectedService)

    { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE"); 10 productService.save(swap); 11 } Injection 3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 } INJECTION
  59. 1 private ProductService productService; 2 3 public void setProductService(ProductService injectedService)

    { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE"); 10 productService.save(swap); 11 } Injection 8 Swap swap = (Swap) productService.getProduct(id); UTILISATION
  60. Injection 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock

    5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 }
  61. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5

    private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } Injection 4 @Mock 5 private ProductService productService; MOCK
  62. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5

    private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } Injection 1 @InjectMocks 2 private BankAccount bankAccount; INJECTION AUTOMATIQUE DES MOCKS
  63. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5

    private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } Injection 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap);
  64. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5

    private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } 14 bankAccount.validateSwap("fakeId"); Injection
  65. Injection 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock

    5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } 16 assertEquals("VALIDATE", swap.getState());
  66. Sans injecteur ? 1 public void validateSwap(String id) { 2

    Swap swap = (Swap) ProductService.getInstance().getProduct(id); 3 swap.updateState("VALIDATE"); 4 ProductService.getInstance().save(swap); 5 }
  67. 1 public void validateSwap(String id) { 2 Swap swap =

    (Swap) ProductService.getInstance().getProduct(id); 3 swap.updateState("VALIDATE"); 4 ProductService.getInstance().save(swap); 5 } Sans injecteur ? ProductService.getInstance() 4 ProductService.getInstance() EXTRACT METHOD !
  68. 1 public ProductService getProductService() { 2 return ProductService.getInstance(); 3 }

    4 5 public void validateSwap(String id) { 6 Swap swap = (Swap) getProductService().getProduct(id); 7 swap.updateState("VALIDATE"); 8 getProductService().save(swap); 9 } Sans injecteur ? 1 public ProductService getProductService() { 2 return ProductService.getInstance(); 3 } getProductService() 8 getProductService()
  69. Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount =

    new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 }
  70. 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23,

    "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); REDÉFINITION DES MÉTHODES POSSIBLE
  71. 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23,

    "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } Sans injecteur ? 11 Mockito.doReturn(productService).when(bankAccount).getProductService();
  72. 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23,

    "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } Sans injecteur ? 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap);
  73. Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount =

    new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } 16 bankAccount.validateSwap("fakeId");
  74. Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount =

    new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } 18 assertEquals("VALIDATE", swap.getState());
  75. Singleton ? 1 public class ProductService { 2 3 private

    static ProductService instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static ProductService getInstance() { 10 return instance; 11 } 12 }
  76. 1 public class ProductService { 2 3 private static ProductService

    instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static ProductService getInstance() { 10 return instance; 11 } 12 } Singleton ? 3 private static ProductService instance = new ProductService(); CRÉATION DE L’INSTANCE AU CHARGEMENT DE LA CLASS
  77. 1 public class ProductService { 2 3 private static ProductService

    instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static ProductService getInstance() { 10 return instance; 11 } 12 } 5 private ProductService() { Singleton ? INSTANCIATION IMPOSSIBLE
  78. 1 public class ProductService { 2 3 private static ProductService

    instance = null; 4 5 public ProductService() { 6 7 } 8 9 public static ProductService getInstance() { 10 if(instance == null) { 11 instance = new ProductService(); 12 } 13 return instance; 14 } 15 } Singleton ? 5 public ProductService() { 6 7 } CONSTRUCTEUR PUBLIC
  79. 1 public class ProductService { 2 3 private static ProductService

    instance = null; 4 5 public ProductService() { 6 7 } 8 9 public static ProductService getInstance() { 10 if(instance == null) { 11 instance = new ProductService(); 12 } 13 return instance; 14 } 15 } Singleton ? 9 public static ProductService getInstance() { 10 if(instance == null) { 11 instance = new ProductService(); 12 } 13 return instance; 14 } CHARGEMENT TARDIF
  80. Singleton ? 1 public class ProductService { 2 3 private

    static ProductService instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static ProductService getInstance() { 10 return instance; 11 } 12 }
  81. 1 public class ProductService implements IProductService { 2 3 private

    static IProductService instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static IProductService getInstance() { 10 return instance; 11 } 12 } Singleton ? implements IProductService { 3 private static IProductService instance 9 public static IProductService getInstance() { 10 return instance; 11 } NIVEAU SUPPLÉMENTAIRE VIA UNE INTERFACE