Resistance is futile mocks will be assimilated

5,083 views
5,060 views

Published on

Conference given at Codemotion Madrid 2013 about writing tests not only using mocks.

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,083
On SlideShare
0
From Embeds
0
Number of Embeds
3,820
Actions
Shares
0
Downloads
33
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

Resistance is futile mocks will be assimilated

  1. 1. Alex Soto Resistance is Futile, Mocks Will be Assimilated asotobu@gmail.com - Everis viernes 18 de octubre de 13
  2. 2. Mocks ? Alex Soto Mocks are objects preprogrammed with expectations viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  3. 3. Mocks ? Alex Soto Mocks are objects preprogrammed with expectations viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  4. 4. Mocks ? Alex Soto Fast viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  5. 5. Mocks ? Alex Soto Fast Interface viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  6. 6. Mocks ? Alex Soto Fast Interface viernes 18 de octubre de 13 www.lordofthejars - @alexsotob 70% Test Code
  7. 7. Mocks ? Alex Soto Fast Interface viernes 18 de octubre de 13 www.lordofthejars - @alexsotob 70% Test Code Hard to Maintain
  8. 8. Mocks ? Alex Soto Fast Interface www.lordofthejars - @alexsotob 70% Test Code Hard to Maintain Container services viernes 18 de octubre de 13
  9. 9. Mocks ? Alex Soto Fast Interface www.lordofthejars - @alexsotob 70% Test Code Hard to Maintain Container services Uncertainty viernes 18 de octubre de 13
  10. 10. Mocks ? Alex Soto Fast Interface www.lordofthejars - @alexsotob 70% Test Code Hard to Maintain Container services Uncertainty Duplication viernes 18 de octubre de 13
  11. 11. Mocks ? Kn ow En Y em ou y? r Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  12. 12. Java EE Scenario Alex Soto www.lordofthejars - @alexsotob {text/html} {app/json} {app/xml} {app/json} Client viernes 18 de octubre de 13 Protocol Server External
  13. 13. High Level Tests Alex Soto www.lordofthejars - @alexsotob e e W viernes 18 de octubre de 13 D ’t on im T ve a H
  14. 14. Low Level Tests Alex Soto State Of The Union viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  15. 15. Data Layer Alex Soto www.lordofthejars - @alexsotob Mock DAOs viernes 18 de octubre de 13
  16. 16. Data Layer Alex Soto www.lordofthejars - @alexsotob Mock DAOs Fast Isolated viernes 18 de octubre de 13
  17. 17. Data Layer Alex Soto www.lordofthejars - @alexsotob Mock DAOs Fast Isolated ORM Mapping ORM Configuration Queries viernes 18 de octubre de 13
  18. 18. Data Layer Alex Soto www.lordofthejars - @alexsotob Fast viernes 18 de octubre de 13
  19. 19. Data Layer Alex Soto www.lordofthejars - @alexsotob Fast viernes 18 de octubre de 13
  20. 20. Data Layer Alex Soto www.lordofthejars - @alexsotob Fast viernes 18 de octubre de 13
  21. 21. Data Layer Alex Soto www.lordofthejars - @alexsotob Isolated viernes 18 de octubre de 13
  22. 22. Data Layer Alex Soto www.lordofthejars - @alexsotob Isolated viernes 18 de octubre de 13
  23. 23. Data Layer Alex Soto www.lordofthejars - @alexsotob Isolated Define base data set viernes 18 de octubre de 13 CLEAN INSERT
  24. 24. Data Layer Alex Soto www.lordofthejars - @alexsotob { ! ! ! ! } "Book": ! ! [ ! ! ! ! ! ] {"title":"The Hobbit","numberOfPages":293} @Rule public MongoDbRule remoteMongoDbRule = newMongoDbRule().defaultManagedMongoDb("db"); @Test @UsingDataSet(locations="data.json",loadStrategy=LoadStrategyEnum.CL EAN_INSERT) @ShouldMatchDataSet(location="expectedData.json") public void book_should_be_inserted_into_repository() { //test } viernes 18 de octubre de 13
  25. 25. Data Layer Alex Soto www.lordofthejars - @alexsotob { ! ! ! ! } "Book": ! ! [ ! ! ! ! ! ] {"title":"The Hobbit","numberOfPages":293} @Rule public MongoDbRule remoteMongoDbRule = newMongoDbRule().defaultManagedMongoDb("db"); @Test @UsingDataSet(locations="data.json",loadStrategy=LoadStrategyEnum.CL EAN_INSERT) @ShouldMatchDataSet(location="expectedData.json") public void book_should_be_inserted_into_repository() { //test } viernes 18 de octubre de 13
  26. 26. Data Layer Alex Soto www.lordofthejars - @alexsotob { ! ! ! ! } "Book": ! ! [ ! ! ! ! ! ] {"title":"The Hobbit","numberOfPages":293} @Rule public MongoDbRule remoteMongoDbRule = newMongoDbRule().defaultManagedMongoDb("db"); @Test @UsingDataSet(locations="data.json",loadStrategy=LoadStrategyEnum.CL EAN_INSERT) @ShouldMatchDataSet(location="expectedData.json") public void book_should_be_inserted_into_repository() { //test } viernes 18 de octubre de 13
  27. 27. Data Layer Alex Soto www.lordofthejars - @alexsotob { ! ! ! ! } "Book": ! ! [ ! ! ! ! ! ] {"title":"The Hobbit","numberOfPages":293} @Rule public MongoDbRule remoteMongoDbRule = newMongoDbRule().defaultManagedMongoDb("db"); @Test @UsingDataSet(locations="data.json",loadStrategy=LoadStrategyEnum.CL EAN_INSERT) @ShouldMatchDataSet(location="expectedData.json") public void book_should_be_inserted_into_repository() { //test } viernes 18 de octubre de 13
  28. 28. E-mail Alex Soto www.lordofthejars - @alexsotob Mock E-mail access viernes 18 de octubre de 13
  29. 29. E-mail Alex Soto www.lordofthejars - @alexsotob Mock E-mail access Fast Offline viernes 18 de octubre de 13
  30. 30. E-mail Alex Soto www.lordofthejars - @alexsotob Mock E-mail access Fast Offline javax.mail viernes 18 de octubre de 13
  31. 31. E-mail Alex Soto www.lordofthejars - @alexsotob SMTPMailService.sendMail(MailMessageBuilder$MailMessage) Transport.send(Message) Transport.send0(Message, Address[]) SMTPTransport.sendMessage(Message, Address[]) MimeMessage.writeTo(OutputStream, String[]) MimeBodyPart.writeTo(MimePart, OutputStream, String[]) viernes 18 de octubre de 13
  32. 32. E-mail Alex Soto www.lordofthejars - @alexsotob Embeddable SMTP server viernes 18 de octubre de 13
  33. 33. E-mail Alex Soto www.lordofthejars - @alexsotob private static final int SMTP_PORT = 2500; private static Wiser mailServer = new Wiser(); @BeforeClass public static void startWiser() { ! mailServer.setPort(SMTP_PORT); ! mailServer.start(); } @AfterClass public static void stopWiser() { ! mailServer.stop(); } @Test public void an_email_should_be_sent() throws MessagingException, IOException { ! ! ! ! ! ! SMTPMailService smtpMailService = getMailService(); smtpMailService.sendMail(message); ! ! ! ! } viernes 18 de octubre de 13 MailMessage message = mail().from("me@mail.com").addTo("you@mail.com") ! ! ! .contentType("text/plain").subject("Welcome") ! ! ! .body("Welcome to our site, thanks for registering on it.") ! ! ! .build(); WiserMessage sentMessage = getSentMessage(); ! String subject = sentMessage.getMimeMessage().getSubject(); assertThat(subject, is("Welcome"));! !
  34. 34. E-mail Alex Soto www.lordofthejars - @alexsotob private static final int SMTP_PORT = 2500; private static Wiser mailServer = new Wiser(); @BeforeClass public static void startWiser() { ! mailServer.setPort(SMTP_PORT); ! mailServer.start(); } @AfterClass public static void stopWiser() { ! mailServer.stop(); } @Test public void an_email_should_be_sent() throws MessagingException, IOException { ! ! ! ! ! ! SMTPMailService smtpMailService = getMailService(); smtpMailService.sendMail(message); ! ! ! ! } viernes 18 de octubre de 13 MailMessage message = mail().from("me@mail.com").addTo("you@mail.com") ! ! ! .contentType("text/plain").subject("Welcome") ! ! ! .body("Welcome to our site, thanks for registering on it.") ! ! ! .build(); WiserMessage sentMessage = getSentMessage(); ! String subject = sentMessage.getMimeMessage().getSubject(); assertThat(subject, is("Welcome"));! !
  35. 35. E-mail Alex Soto www.lordofthejars - @alexsotob private static final int SMTP_PORT = 2500; private static Wiser mailServer = new Wiser(); @BeforeClass public static void startWiser() { ! mailServer.setPort(SMTP_PORT); ! mailServer.start(); } @AfterClass public static void stopWiser() { ! mailServer.stop(); } @Test public void an_email_should_be_sent() throws MessagingException, IOException { ! ! ! ! ! ! SMTPMailService smtpMailService = getMailService(); smtpMailService.sendMail(message); ! ! ! ! } viernes 18 de octubre de 13 MailMessage message = mail().from("me@mail.com").addTo("you@mail.com") ! ! ! .contentType("text/plain").subject("Welcome") ! ! ! .body("Welcome to our site, thanks for registering on it.") ! ! ! .build(); WiserMessage sentMessage = getSentMessage(); ! String subject = sentMessage.getMimeMessage().getSubject(); assertThat(subject, is("Welcome"));! !
  36. 36. E-mail Alex Soto www.lordofthejars - @alexsotob private static final int SMTP_PORT = 2500; private static Wiser mailServer = new Wiser(); @BeforeClass public static void startWiser() { ! mailServer.setPort(SMTP_PORT); ! mailServer.start(); } @AfterClass public static void stopWiser() { ! mailServer.stop(); } @Test public void an_email_should_be_sent() throws MessagingException, IOException { ! ! ! ! ! ! SMTPMailService smtpMailService = getMailService(); smtpMailService.sendMail(message); ! ! ! ! } viernes 18 de octubre de 13 MailMessage message = mail().from("me@mail.com").addTo("you@mail.com") ! ! ! .contentType("text/plain").subject("Welcome") ! ! ! .body("Welcome to our site, thanks for registering on it.") ! ! ! .build(); WiserMessage sentMessage = getSentMessage(); ! String subject = sentMessage.getMimeMessage().getSubject(); assertThat(subject, is("Welcome"));! !
  37. 37. REST Alex Soto www.lordofthejars - @alexsotob Mock REST access viernes 18 de octubre de 13
  38. 38. REST Alex Soto www.lordofthejars - @alexsotob Mock REST access Fast Offline viernes 18 de octubre de 13
  39. 39. REST Alex Soto www.lordofthejars - @alexsotob Mock REST access Fast Offline Full Call Stack viernes 18 de octubre de 13
  40. 40. REST Alex Soto www.lordofthejars - @alexsotob Stubbing Web Services viernes 18 de octubre de 13
  41. 41. REST Alex Soto www.lordofthejars - @alexsotob private static final String URL = "http://localhost:8089"; @Rule public WireMockRule wireMockRule = new WireMockRule(8089); ! @Test public void issues_from_project_should_be_retrieved() { ! ! ! givenThat(get(urlEqualTo("/repos/lordofthejars/nosqlunit/issues")) ! ! .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(GET_RESPONSE_JSON)) ! ); ! ! ! GithubClient githubClient = new GithubClient(URL); ! ! ! String issues = githubClient.invokeGetMethod("/repos/lordofthejars/ nosqlunit/issues"); ! ! } viernes 18 de octubre de 13 //could be an object assertThat(issues, is(GET_RESPONSE_JSON)); !
  42. 42. REST Alex Soto www.lordofthejars - @alexsotob private static final String URL = "http://localhost:8089"; @Rule public WireMockRule wireMockRule = new WireMockRule(8089); ! @Test public void issues_from_project_should_be_retrieved() { ! ! ! givenThat(get(urlEqualTo("/repos/lordofthejars/nosqlunit/issues")) ! ! .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(GET_RESPONSE_JSON)) ! ); ! ! ! GithubClient githubClient = new GithubClient(URL); ! ! ! String issues = githubClient.invokeGetMethod("/repos/lordofthejars/ nosqlunit/issues"); ! ! } viernes 18 de octubre de 13 //could be an object assertThat(issues, is(GET_RESPONSE_JSON)); !
  43. 43. REST Alex Soto www.lordofthejars - @alexsotob private static final String URL = "http://localhost:8089"; @Rule public WireMockRule wireMockRule = new WireMockRule(8089); ! @Test public void issues_from_project_should_be_retrieved() { ! ! ! givenThat(get(urlEqualTo("/repos/lordofthejars/nosqlunit/issues")) ! ! .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(GET_RESPONSE_JSON)) ! ); ! ! ! GithubClient githubClient = new GithubClient(URL); ! ! ! String issues = githubClient.invokeGetMethod("/repos/lordofthejars/ nosqlunit/issues"); ! ! } viernes 18 de octubre de 13 //could be an object assertThat(issues, is(GET_RESPONSE_JSON)); !
  44. 44. REST Alex Soto www.lordofthejars - @alexsotob private static final String URL = "http://localhost:8089"; @Rule public WireMockRule wireMockRule = new WireMockRule(8089); ! @Test public void issues_from_project_should_be_retrieved() { ! ! ! givenThat(get(urlEqualTo("/repos/lordofthejars/nosqlunit/issues")) ! ! .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(GET_RESPONSE_JSON)) ! ); ! ! ! GithubClient githubClient = new GithubClient(URL); ! ! ! String issues = githubClient.invokeGetMethod("/repos/lordofthejars/ nosqlunit/issues"); ! ! } viernes 18 de octubre de 13 //could be an object assertThat(issues, is(GET_RESPONSE_JSON)); !
  45. 45. Container Alex Soto Code Runs in Container viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  46. 46. Container Alex Soto www.lordofthejars - @alexsotob Code Runs in Container CDI (Qualifiers, Produces, Alternatives, Decorators) JPA (EntityManager, Transactions, Mapping) Security JSF (Conversation Scope, Binding,Validation) JAX-RS, JAX-WS, ... viernes 18 de octubre de 13
  47. 47. Container Alex Soto www.lordofthejars - @alexsotob public class PaymentGateway { @Inject @CreditCard PaymentProcessor paymentProcessor //... public void setPaymentProcessor(PaymentProcessor paymentProcessor) {...} } Are you sure it works? viernes 18 de octubre de 13
  48. 48. Container Alex Soto Brings tests to runtime viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  49. 49. Container Alex Soto Brings tests to runtime Manage Lifecycle of Container viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  50. 50. Container Alex Soto www.lordofthejars - @alexsotob Brings tests to runtime Manage Lifecycle of Container Create/Deploy MicroDeployments viernes 18 de octubre de 13
  51. 51. Container Alex Soto www.lordofthejars - @alexsotob Brings tests to runtime Manage Lifecycle of Container Create/Deploy MicroDeployments Enriching Test Classes viernes 18 de octubre de 13
  52. 52. Container Alex Soto www.lordofthejars - @alexsotob Brings tests to runtime Manage Lifecycle of Container Create/Deploy MicroDeployments Enriching Test Classes Run Tests Inside/Against Container viernes 18 de octubre de 13
  53. 53. Container Alex Soto www.lordofthejars - @alexsotob Brings tests to runtime Manage Lifecycle of Container Create/Deploy MicroDeployments Enriching Test Classes Run Tests Inside/Against Container IDE Friendly viernes 18 de octubre de 13
  54. 54. Container Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  55. 55. Container Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  56. 56. Container Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  57. 57. Alex Soto Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  58. 58. Container Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  59. 59. Container Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  60. 60. Slide’s title Speaker’s name Let’s see in Action viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  61. 61. UI Alex Soto www.lordofthejars - @alexsotob UI code DOM Manipulation Ajax Widgets viernes 18 de octubre de 13
  62. 62. UI Alex Soto www.lordofthejars - @alexsotob Drives the browser Access web elements viernes 18 de octubre de 13
  63. 63. UI Alex Soto www.lordofthejars - @alexsotob driver.get(contextPath.toString()+"login.xhtml"); ! ! WebElement username = driver.findElement(By.id("username")); WebElement password = driver.findElement(By.id("password")); WebElement submit = driver.findElement(By.id("submit")); ! ! username.sendKeys("aa"); password.sendKeys("bb"); ! ! submit.click(); ! ! WebElement welcomeMessage = driver.findElement(By.id("welcomeMessage")); assertThat(welcomeMessage.getText(), is("Welcome")); viernes 18 de octubre de 13
  64. 64. UI Alex Soto www.lordofthejars - @alexsotob driver.get(contextPath.toString()+"login.xhtml"); ! ! WebElement username = driver.findElement(By.id("username")); WebElement password = driver.findElement(By.id("password")); WebElement submit = driver.findElement(By.id("submit")); ! ! username.sendKeys("aa"); password.sendKeys("bb"); ! ! submit.click(); ! ! WebElement welcomeMessage = driver.findElement(By.id("welcomeMessage")); assertThat(welcomeMessage.getText(), is("Welcome")); viernes 18 de octubre de 13
  65. 65. UI Alex Soto www.lordofthejars - @alexsotob Arquillian Drone/Graphene Sexy WebDriver API Ajax-enabled PageObjects JQuery selectors Call Javascript as Java viernes 18 de octubre de 13
  66. 66. UI Alex Soto Let’s see in Action viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  67. 67. Faults Alex Soto www.lordofthejars - @alexsotob Mock Fauls viernes 18 de octubre de 13
  68. 68. Faults Alex Soto www.lordofthejars - @alexsotob Mock Fauls Race Conditions Uncommon Exceptions viernes 18 de octubre de 13
  69. 69. Faults Alex Soto www.lordofthejars - @alexsotob Mock Fauls Race Conditions Uncommon Exceptions Test Until Last Line viernes 18 de octubre de 13
  70. 70. Faults Alex Soto www.lordofthejars - @alexsotob Fault Injection Modify Bytecode viernes 18 de octubre de 13
  71. 71. Faults Alex Soto www.lordofthejars - @alexsotob @Test(expected = ”IOException.class”) @BMRule( ! ! name="throw IOException writting content", ! ! targetClass = "com.lordofthejars.byteman.util.FileUtils", ! ! targetMethod = "createFileWithContent", ! ! targetLocation = "CALL BufferedWriter.write(String)", ! ! action = "throw new java.io.IOException()" ! ! ) public void an_exception_should_be_thrown() throws IOException { ! ! ! BackupManager backupManager = createBackupManager();! ! ! backupManager.backupData("Hello World"); ! ! } public void createFileWithContent(File filename, String content) throws IOException { ! ! } viernes 18 de octubre de 13 ! ! ! ! BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(content);
  72. 72. Faults Alex Soto www.lordofthejars - @alexsotob @Test(expected = ”IOException.class”) @BMRule( ! ! name="throw IOException writting content", ! ! targetClass = "com.lordofthejars.byteman.util.FileUtils", ! ! targetMethod = "createFileWithContent", ! ! targetLocation = "CALL BufferedWriter.write(String)", ! ! action = "throw new java.io.IOException()" ! ! ) public void an_exception_should_be_thrown() throws IOException { ! ! ! BackupManager backupManager = createBackupManager();! ! ! backupManager.backupData("Hello World"); ! ! } public void createFileWithContent(File filename, String content) throws IOException { ! ! } viernes 18 de octubre de 13 ! ! ! ! BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(content);
  73. 73. Faults Alex Soto www.lordofthejars - @alexsotob @Test(expected = ”IOException.class”) @BMRule( ! ! name="throw IOException writting content", ! ! targetClass = "com.lordofthejars.byteman.util.FileUtils", ! ! targetMethod = "createFileWithContent", ! ! targetLocation = "CALL BufferedWriter.write(String)", ! ! action = "throw new java.io.IOException()" ! ! ) public void an_exception_should_be_thrown() throws IOException { ! ! ! BackupManager backupManager = createBackupManager();! ! ! backupManager.backupData("Hello World"); ! ! } public void createFileWithContent(File filename, String content) throws IOException { ! ! } viernes 18 de octubre de 13 ! ! ! ! BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(content);
  74. 74. Continuous Integration/Delivery Alex Soto Continuous Integration / Delivery viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  75. 75. Continuous Integration/Delivery Alex Soto Continuous Integration / Delivery Commit Stage viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  76. 76. Continuous Integration/Delivery Alex Soto Continuous Integration / Delivery Commit Stage Mock Expensive Operations viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  77. 77. Continuous Integration/Delivery Alex Soto Continuous Integration / Delivery Commit Stage Mock Expensive Operations Monitor Tests viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  78. 78. Continuous Integration/Delivery Alex Soto Continuous Integration / Delivery Commit Stage Mock Expensive Operations Monitor Tests Bye Bye Uncertainty viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  79. 79. Recap Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  80. 80. Recap Alex Soto Mock is an option, not a rule viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  81. 81. Recap Alex Soto Mock is an option, not a rule Tests are first citizens viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  82. 82. Recap Alex Soto www.lordofthejars - @alexsotob Mock is an option, not a rule Tests are first citizens Don’t let mocks ruin your quality viernes 18 de octubre de 13
  83. 83. Recap Alex Soto www.lordofthejars - @alexsotob Mock is an option, not a rule Tests are first citizens Don’t let mocks ruin your quality Remember TDD viernes 18 de octubre de 13
  84. 84. Recap Alex Soto www.lordofthejars - @alexsotob Mock is an option, not a rule Tests are first citizens Don’t let mocks ruin your quality Remember TDD Long Live and Prosper to Tests viernes 18 de octubre de 13
  85. 85. Engage Alex Soto viernes 18 de octubre de 13 www.lordofthejars - @alexsotob
  86. 86. Contents Alex Soto www.lordofthejars - @alexsotob https://github.com/lordofthejars/foobank/ viernes 18 de octubre de 13
  87. 87. Questions? Alex Soto www.lordofthejars - @alexsotob Alex Soto www.lordofthejars.com @alexsotob Let the end of the world come tumbling down, I'll be the last man standing on the ground - Alive - MeatLoaf viernes 18 de octubre de 13

×