Testing made sweet with a Mockito

Testing made sweet with a Mockito

Slides from my talk at Droidcon Berlin and Big Android BBQ Amsterdam 2016
audio: https://voicerepublic.com/talks/testing-made-sweet-with-a-mockito

The past year has been huge for Android testing: Testing support lib, fast JVM unit tests,... Having such great tools means writing tests is a breeze! All your apps currently have >80% code coverage, right? Yay! Or wait... is it really? Is all your common Android logic (networking, databases,...) tested? Do you isolate parts of your code base to keep your tests small? And what about providing relevant testing data?

In order to achieve this, you need to make use of mocks and stubs. And that's exactly what this talk will be about: What is a mock? What's the difference between a mock and a stub? Are mocks the only way to provide relevant data for your unit tests? What do I do with all the final classes/methods in the Android SDK? How do I architect my app to make it easier to test? ...

After having adopted TDD as my main development workflow for almost a year now, I feel comfortable saying everything can be tested. Its just a matter of having someone experience show you how.

5f57d2d205e77e185986459c1b89a874?s=128

Jeroen Mols

June 16, 2016
Tweet

Transcript

  1. TESTING MADE SWEET WITH A MOCKITO @MOLSJEROEN

  2. @MOLSJEROEN @MOLSJEROEN

  3. IF YOU DON’T LIKE UNIT TESTING YOUR PRODUCT, MOST LIKELY

    YOUR CUSTOMERS WON’T LIKE TO TEST IT EITHER. Unknown
  4. ALWAYS WRITE A TEST TO REPRODUCE A BUG BEFORE YOU

    FIX IT Robert C. Martin*
  5. @MOLSJEROEN GOAL UI USER WEBSERVICE Button press Login/logout command Success/failure

    Update UI LOGININTERFACE RESPONSE
  6. @MOLSJEROEN GOAL UI USER WEBSERVICE Button press Login/logout command Success/failure

    Update UI LOGININTERFACE RESPONSE
  7. WAY OF WORKING

  8. @MOLSJEROEN TEST REQUIREMENTS ▸ All tests must ▸ Run really

    fast ▸ Be small and focussed ▸ Reliable, not “flaky” ▸ Challenges: UI & WebService UI USER WEBSERVICE
  9. @MOLSJEROEN SOLUTION ▸ Isolate User ▸ Don’t include UI ▸

    Replace WebService with dummy ▸ Mimic WebService behaviour ▸ => Verify interactions UI USER WEBSERVICE*
  10. @MOLSJEROEN DEFINITION: TEST DOUBLES ▸ Replace real class ▸ Same

    interface ▸ Different behaviour WEBSERVICE* WEBSERVICE public void login() { 
 // NORMAL IMPL. 
 } public void login() { 
 // DO NOTHING 
 }
  11. @MOLSJEROEN DEFINITION: TEST DOUBLES ▸ Replace real class ▸ Same

    interface ▸ Different behaviour WEBSERVICE* WEBSERVICE public void login() { 
 // NORMAL IMPL. 
 } public void login() { 
 // DO NOTHING 
 }
  12. @MOLSJEROEN DEFINITION: TEST DOUBLES ▸ Replace real class ▸ Same

    interface ▸ Different behaviour WEBSERVICE* WEBSERVICE public void login() { 
 // NORMAL IMPL. 
 } public void login() { 
 loginInterface.success(); 
 }
  13. @MOLSJEROEN DEFINITION: TEST DOUBLES ▸ Replace real class ▸ Same

    interface ▸ Different behaviour WEBSERVICE* WEBSERVICE public void login() { 
 // NORMAL IMPL. 
 } public void login() { 
 throw new Exception(); 
 }
  14. @MOLSJEROEN DEFINITION: MOCKS AND STUBS ▸ What is a mock?

    ▸ Generated class ▸ Doesn’t do anything ▸ Behaviour verification ▸ What is a stub? ▸ Handwritten class ▸ Returns predefined responses ▸ State verification
  15. MOCKITO

  16. @MOLSJEROEN Open source mocking framework that lets you write beautiful

    tests with a clean & simple API ▸ Documentation on mockito.org ▸ Source code on Github ▸ MIT license WHAT IS IT?
  17. @MOLSJEROEN WHY DRINK IT? ▸ Easy to use ▸ Very

    readable syntax ▸ No learning curve ▸ Annotation support ▸ Mature ▸ Large stackoverflow community ▸ Most popular Java / Android mocking framework
  18. @MOLSJEROEN HOW TO DRINK IT? ▸ PROJECT_HOME/build.gradle buildscript {
 repositories

    {
 jcenter()
 }
 }
 
 ▸ MODULE_HOME/build.gradle dependencies {
 ... 
 testCompile "org.mockito:mockito-core:2.0.101-beta"
 }
  19. @MOLSJEROEN HOW TO DRINK IT? ▸ PROJECT_HOME/build.gradle buildscript {
 repositories

    {
 jcenter()
 }
 }
 
 ▸ MODULE_HOME/build.gradle dependencies {
 ... 
 testCompile "org.mockito:mockito-core:2.0.101-beta"
 }
  20. INGREDIENTS

  21. @MOLSJEROEN INGREDIENTS ▸ Creating a mock ▸ Verifying interactions ▸

    Stubbing methods ▸ Capturing arguments ▸ Mockito limitations
  22. @MOLSJEROEN INGREDIENTS ▸ Creating a mock ▸ Verifying interactions ▸

    Stubbing methods ▸ Capturing arguments ▸ Mockito limitations
  23. @MOLSJEROEN CREATING A MOCK import static org.mockito.Mockito.mock; @Test
 public void

    createMock() throws Exception {
 WebService mockWebService = mock(WebService.class);
 
 new User(mockWebService, 0, null);
 }
  24. @MOLSJEROEN CREATING A MOCK import static org.mockito.Mockito.mock; @Test
 public void

    createMock() throws Exception {
 WebService mockWebService = mock(WebService.class);
 
 new User(mockWebService, 0, null);
 }
  25. @MOLSJEROEN CREATING A MOCK import static org.mockito.Mockito.mock; @Test
 public void

    createMock() throws Exception {
 WebService mockWebService = mock(WebService.class);
 
 new User(mockWebService, 0, null);
 }
  26. @MOLSJEROEN CREATING A MOCK - ANNOTATION @Rule
 public MockitoRule mockitoRule

    = MockitoJUnit.rule();
 
 @Mock
 private WebService mockWebService; @Test
 public void createMockUsingAnnotation() throws Exception {
 new User(mockWebService, 0, null);
 }
  27. @MOLSJEROEN CREATING A MOCK - ANNOTATION @Rule
 public MockitoRule mockitoRule

    = MockitoJUnit.rule();
 
 @Mock
 private WebService mockWebService; @Test
 public void createMockUsingAnnotation() throws Exception {
 new User(mockWebService, 0, null);
 }
  28. @MOLSJEROEN CREATING A MOCK - ANNOTATION @Rule
 public MockitoRule mockitoRule

    = MockitoJUnit.rule();
 
 @Mock
 private WebService mockWebService; @Test
 public void createMockUsingAnnotation() throws Exception {
 new User(mockWebService, 0, null);
 }
  29. @MOLSJEROEN INGREDIENTS ▸ Creating a mock ▸ Verifying interactions ▸

    Stubbing methods ▸ Capturing arguments ▸ Mockito limitations
  30. @MOLSJEROEN VERIFYING INTERACTIONS @Test
 public void verifyInteractionTimes() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.logout();
 
 verify(mockWebService).logout();
 }
  31. @MOLSJEROEN VERIFYING INTERACTIONS @Test
 public void verifyInteractionTimes() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.logout();
 
 verify(mockWebService).logout();
 }
  32. @MOLSJEROEN VERIFYING INTERACTIONS - TIMES @Test
 public void verifyInteractionTimes() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.logout();
 
 verify(mockWebService, times(1) ).logout();
 atLeast(1)
 atLeastOnce()
 atMost(1)
 only()
 never()
 }
  33. @MOLSJEROEN VERIFYING INTERACTIONS - TIMES @Test
 public void verifyInteractionTimes() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.logout();
 
 verify(mockWebService, times(1) ).logout();
 atLeast(1)
 atLeastOnce()
 atMost(1)
 only()
 never()
 } ▸ Being overly restrictive makes tests brittle!
  34. @MOLSJEROEN VERIFYING INTERACTIONS - PARAMETERS @Test
 public void verifyInteractionParameters() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 
 verify(mockWebService).login(USER_ID);
 }
  35. @MOLSJEROEN VERIFYING INTERACTIONS - PARAMETERS @Test
 public void verifyInteractionParameters() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 
 verify(mockWebService).login(anyInt() ); anyString() any(Response.class)
 }
  36. @MOLSJEROEN VERIFYING INTERACTIONS - PARAMETERS @Test
 public void verifyInteractionParameters() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 
 verify(mockWebService).login(anyInt(), eq(PASSWORD));
 } ▸ One matcher -> all arguments need to be matchers
  37. @MOLSJEROEN VERIFYING INTERACTIONS - PARAMETERS @Test
 public void verifyInteractionParameters() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 
 verify(mockWebService).login(gt(0) );
 lt(10000) leq(10000)
 }
  38. @MOLSJEROEN VERIFYING INTERACTIONS - PARAMETERS @Test
 public void verifyInteractionParameters() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 
 verify(mockWebService).login(startsWith(“n1") );
 contains(“c3") matches("n[1-9]{1}c[1-9]{1}[a-z]{3}") }
  39. @MOLSJEROEN VERIFYING INTERACTIONS - PARAMETERS @Test
 public void verifyInteractionParameters() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 
 verify(mockWebService).login(isNotNull(Response.class)) ); not(eq(0)) not(eq(“12345678")) and(gt(0), lt(Integer.MAX_VALUE))
 } ▸ Mockito.Matchers ▸ Mockito.AdditionalMatchers
  40. @MOLSJEROEN VERIFYING INTERACTIONS - ORDER @Test
 public void verifyInteractionOrder() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 user.logout();
 
 InOrder inOrder = inOrder(mockWebService);
 inOrder.verify(mockWebService).login();
 inOrder.verify(mockWebService).logout();
 }
  41. @MOLSJEROEN VERIFYING INTERACTIONS - ORDER @Test
 public void verifyInteractionOrder() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 user.logout();
 
 InOrder inOrder = inOrder(mockWebService);
 inOrder.verify(mockWebService).login();
 inOrder.verify(mockWebService).logout();
 }
  42. @MOLSJEROEN VERIFYING INTERACTIONS - ORDER @Test
 public void verifyInteractionOrder() throws

    Exception {
 User user = new User(mockWebService, USER_ID, PASSWORD);
 
 user.login(null);
 user.logout();
 
 InOrder inOrder = inOrder(mockWebService);
 inOrder.verify(mockWebService).login();
 inOrder.verify(mockWebService).logout();
 }
  43. @MOLSJEROEN INGREDIENTS ▸ Creating a mock ▸ Verifying interactions ▸

    Stubbing methods ▸ Capturing arguments ▸ Mockito limitations
  44. @MOLSJEROEN STUBBING METHODS @Test
 public void stubMethod() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 when(mockWebService.isOffline()).thenReturn(true);
 
 user.login(mockLoginInterface);
 
 verify(mockWebService, never()).login();
 }
  45. @MOLSJEROEN STUBBING METHODS @Test
 public void stubMethod() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 when(mockWebService.isOffline()).thenReturn(true);
 
 user.login(mockLoginInterface);
 
 verify(mockWebService, never()).login();
 }
  46. @MOLSJEROEN STUBBING METHODS @Test
 public void stubMethod() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 when(mockWebService.isOffline()).thenReturn(true);
 
 user.login(mockLoginInterface);
 
 verify(mockWebService, never()).login();
 }
  47. @MOLSJEROEN STUBBING METHODS @Test
 public void stubMethod() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 when(mockWebService.isOffline()).thenReturn(true, false, true);
 
 user.login(mockLoginInterface);
 
 verify(mockWebService, never()).login();
 }
  48. @MOLSJEROEN STUBBING METHODS @Test
 public void stubMethod() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 when(mockWebService.isOffline()).thenThrow(CustomException.class);
 
 user.login(mockLoginInterface);
 
 verify(mockWebService, never()).login();
 }
  49. @MOLSJEROEN STUBBING METHODS ▸ Normal syntax when(mockWebService.isOffline()).thenReturn(true); 
 ▸ Alternative

    syntax doReturn(true).when(mockWebService).isOffline(); 
 ▸ BDD syntax given(mockWebService.isOffline()).willReturn(true);
  50. @MOLSJEROEN STUBBING METHODS ▸ Normal syntax when(mockWebService.isOffline()).thenReturn(true); 
 ▸ Alternative

    syntax doReturn(true).when(mockWebService).isOffline(); 
 ▸ BDD syntax given(mockWebService.isOffline()).willReturn(true);
  51. @MOLSJEROEN STUBBING METHODS ▸ Normal syntax when(mockWebService.isOffline()).thenReturn(true); 
 ▸ Alternative

    syntax doReturn(true).when(mockWebService).isOffline(); 
 ▸ BDD syntax given(mockWebService.isOffline()).willReturn(true);
  52. @MOLSJEROEN INGREDIENTS ▸ Creating a mock ▸ Verifying interactions ▸

    Stubbing methods ▸ Capturing arguments ▸ Mockito limitations
  53. @MOLSJEROEN CAPTURING ARGUMENTS @Test
 public void captureArguments() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 user.login(mockLoginInterface);
 verify(mockWebService).login(responseArgumentCaptor.capture());
 Response response = responseArgumentCaptor.getValue();
 
 response.onRequestCompleted(true);
 
 verify(mockLoginInterface).onLoginSuccess();
 } UI USER WEBSERVICE LOGININTERFACE RESPONSE
  54. @MOLSJEROEN CAPTURING ARGUMENTS @Captor
 private ArgumentCaptor<Response> responseArgumentCaptor; UI USER WEBSERVICE

    LOGININTERFACE RESPONSE
  55. @MOLSJEROEN CAPTURING ARGUMENTS @Test
 public void captureArguments() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 user.login(mockLoginInterface);
 verify(mockWebService).login(responseArgumentCaptor.capture());
 Response response = responseArgumentCaptor.getValue();
 
 response.onRequestCompleted(true);
 
 verify(mockLoginInterface).onLoginSuccess();
 } UI USER WEBSERVICE LOGININTERFACE RESPONSE
  56. @MOLSJEROEN CAPTURING ARGUMENTS @Test
 public void captureArguments() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 user.login(mockLoginInterface);
 verify(mockWebService).login(responseArgumentCaptor.capture());
 Response response = responseArgumentCaptor.getValue();
 
 response.onRequestCompleted(true);
 
 verify(mockLoginInterface).onLoginSuccess();
 } UI USER WEBSERVICE LOGININTERFACE RESPONSE
  57. @MOLSJEROEN CAPTURING ARGUMENTS @Test
 public void captureArguments() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 user.login(mockLoginInterface);
 verify(mockWebService).login(responseArgumentCaptor.capture());
 Response response = responseArgumentCaptor.getValue();
 
 response.onRequestCompleted(true);
 
 verify(mockLoginInterface).onLoginSuccess();
 } UI USER WEBSERVICE LOGININTERFACE RESPONSE
  58. @MOLSJEROEN CAPTURING ARGUMENTS @Test
 public void captureArguments() throws Exception {


    User user = new User(mockWebService, USER_ID, PASSWORD);
 user.login(mockLoginInterface);
 verify(mockWebService).login(responseArgumentCaptor.capture());
 Response response = responseArgumentCaptor.getValue();
 
 response.onRequestCompleted(true);
 
 verify(mockLoginInterface).onLoginSuccess();
 } UI USER WEBSERVICE LOGININTERFACE RESPONSE
  59. @MOLSJEROEN INGREDIENTS ▸ Creating a mock ▸ Verifying interactions ▸

    Stubbing methods ▸ Capturing arguments ▸ Mockito limitations
  60. @MOLSJEROEN MOCKITO LIMITATIONS ▸ Unable to mock ▸ final classes

    ▸ final methods ▸ static methods ▸ private methods ▸ hashCode() and equals()
  61. ADVANCED MOCKITO

  62. @MOLSJEROEN ▸ Model View Presenter ▸ Mock view & model

    ▸ Fully test presenter ▸ UI layer == “pass through” ▸ Dependency injection ▸ Only “inward pointing” dependencies 1. TESTING UI MODEL VIEW VIEW IMPLEMENTATION PRESENTER
  63. @MOLSJEROEN 2. RUNNING MOCKITO ON A DEVICE ▸ MODULE_HOME/build.gradle defaultConfig

    {
 … 
 testInstrumentationRunner 
 "android.support.test.runner.AndroidJUnitRunner"
 } dependencies {
 … 
 androidTestCompile 'com.android.support.test:runner:0.4'
 androidTestCompile 'com.android.support.test:rules:0.4'
 androidTestCompile 'org.mockito:mockito-core:1.10.19'
 androidTestCompile "com.google.dexmaker:dexmaker:1.2"
 androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
 }
  64. @MOLSJEROEN 2. RUNNING MOCKITO ON A DEVICE ▸ MODULE_HOME/build.gradle defaultConfig

    {
 … 
 testInstrumentationRunner 
 "android.support.test.runner.AndroidJUnitRunner"
 } dependencies {
 … 
 androidTestCompile 'com.android.support.test:runner:0.4'
 androidTestCompile 'com.android.support.test:rules:0.4'
 androidTestCompile 'org.mockito:mockito-core:1.10.19'
 androidTestCompile "com.google.dexmaker:dexmaker:1.2"
 androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
 }
  65. @MOLSJEROEN 2. RUNNING MOCKITO ON A DEVICE ▸ MODULE_HOME/build.gradle defaultConfig

    {
 … 
 testInstrumentationRunner 
 "android.support.test.runner.AndroidJUnitRunner"
 } dependencies {
 … 
 androidTestCompile 'com.android.support.test:runner:0.4'
 androidTestCompile 'com.android.support.test:rules:0.4'
 androidTestCompile 'org.mockito:mockito-core:1.10.19'
 androidTestCompile "com.google.dexmaker:dexmaker:1.2"
 androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
 }
  66. @MOLSJEROEN 3. TESTING FINAL METHODS / CLASSES public class Handler

    {
 
 public Handler() {};
 
 public final boolean post(Runnable r)
 {
 // internal implementation
 }
 
 public final boolean sendMessage(Message msg)
 {
 // internal implementation
 }
 }
  67. @MOLSJEROEN 3. TESTING FINAL METHODS / CLASSES public class Handler

    {
 
 public Handler() {};
 
 public final boolean post(Runnable r)
 {
 // internal implementation
 }
 
 public final boolean sendMessage(Message msg)
 {
 // internal implementation
 }
 }
  68. @MOLSJEROEN 3. TESTING FINAL METHODS / CLASSES public class HandlerWrapper

    {
 
 private final Handler handler;
 
 public HandlerWrapper() {
 handler = new Handler();
 }
 
 public boolean post(Runnable r) {
 return handler.post(r);
 }
 
 public boolean sendMessage(Message msg) {
 return handler.sendMessage(msg);
 }
 }
  69. @MOLSJEROEN 3. TESTING FINAL METHODS / CLASSES public class HandlerWrapper

    {
 
 private final Handler handler;
 
 public HandlerWrapper() {
 handler = new Handler();
 }
 
 public boolean post(Runnable r) {
 return handler.post(r);
 }
 
 public boolean sendMessage(Message msg) {
 return handler.sendMessage(msg);
 }
 }
  70. @MOLSJEROEN 3. TESTING FINAL METHODS / CLASSES public class HandlerWrapper

    {
 
 private final Handler handler;
 
 public HandlerWrapper() {
 handler = new Handler();
 }
 
 public boolean post(Runnable r) {
 return handler.post(r);
 }
 
 public boolean sendMessage(Message msg) {
 return handler.sendMessage(msg);
 }
 }
  71. @MOLSJEROEN 3. TESTING STATIC METHODS public class NativeCamera {
 


    private Camera camera = null;
 
 public Camera getNativeCamera() {
 return camera;
 }
 
 public void openNativeCamera() throws RuntimeException {
 camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
 }
 
 public void releaseNativeCamera() {
 camera.release();
 }
 }
  72. @MOLSJEROEN 3. TESTING STATIC METHODS public class NativeCamera {
 


    private Camera camera = null;
 
 public Camera getNativeCamera() {
 return camera;
 }
 
 public void openNativeCamera() throws RuntimeException {
 camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
 }
 
 public void releaseNativeCamera() {
 camera.release();
 }
 }
  73. @MOLSJEROEN 4. TESTING DATA @Test
 public void mockData() throws Exception

    {
 UserData mock = mock(UserData.class);
 when(mock.getFirstName()).thenReturn("FirstName");
 when(mock.getLastName()).thenReturn("LastName");
 when(mock.getUserId()).thenReturn(1111007);
 
 when(mock.getStreet()).thenReturn("StreetName");
 when(mock.getHouseNumber()).thenReturn(1);
 when(mock.getCity()).thenReturn("City");
 when(mock.getCountry()).thenReturn("Country");
 
 // Use mock in further test
 }
  74. @MOLSJEROEN 4. TESTING DATA @Test
 public void testData() throws Exception

    {
 UserData userData = new TestUserData();
 
 // use mock in further test
 } public class TestUserData extends UserData { @Override
 public String getFirstName() {
 return "FirstName";
 } 
 ... }
  75. @MOLSJEROEN 4. TESTING DATA @Test
 public void testData() throws Exception

    {
 UserData userData = new TestUserData();
 
 // use mock in further test
 } public class TestUserData extends UserData { @Override
 public String getFirstName() {
 return "FirstName";
 } 
 ... }
  76. @MOLSJEROEN 5. NEW CREATION public User(int userId, String password) {


    this.webService = new WebService();
 } ▸ Internal created objects ▸ almost impossible to test ▸ avoid for long lived objects
  77. @MOLSJEROEN 5. NEW CREATION public User(int userId, String password) {


    this.webService = new WebService();
 } ▸ Internal created objects ▸ almost impossible to test ▸ avoid for long lived objects
  78. @MOLSJEROEN 5. NEW CREATION public User(int userId, String password) {


    this.webService = new WebService();
 } ▸ Dependency injection public User(WebService webService, int userId, String password) {
 if (webService == null) {
 throw new RuntimeException("Webservice required");
 }
 this.webService = webService;
 }
  79. @MOLSJEROEN 5. NEW CREATION public User(int userId, String password) {


    this.webService = new WebService();
 } ▸ Factory pattern public User(WebServiceFactory factory, int userId, String password) {
 this.webService = factory.createWebService();
 }
  80. @MOLSJEROEN 6. POWER TIPS ▸ Avoid singletons ▸ Avoid instrumentation

    tests ▸ Isolate non testable code ▸ Don’t use Spies ▸ Don’t nest mocks ▸ Avoid using “For testing methods”
  81. WRAP UP

  82. IT IS BETTER TO HAVE A SIMPLE TEST THAT WORKS

    THAN A COMPLICATED TEST THAT SEEMS TO WORK. Mockito documentation
  83. @MOLSJEROEN CONCLUSION ▸ Mockito makes mocking & stubbing easy ▸

    Avoid creating internal objects ▸ Choose a good testing strategy ▸ Don’t overuse the power features ▸ Keep unit tests small and focussed ▸ Consider refactoring ▸ Prefer tests on the java VM
  84. @MOLSJEROEN REFERENCES ▸ Mockito homepage http://mockito.org/ ▸ Mockito reference card

    https://dzone.com/refcardz/mockito ▸ Dexmaker https://github.com/crittercism/dexmaker ▸ Sample code ▸ MockitoExample https://github.com/JeroenMols/MockitoExample ▸ LandscapeVideoCamera https://github.com/JeroenMols/LandscapeVideoCamera ▸ Legofy https://github.com/JeroenMols/Legofy
  85. @MOLSJEROEN IMAGE CREDITS ▸ Mojito
 https://indraneescookingcorner.blogspot.be/2014/08/virgin-mojito.html ▸ Philips Hue living

    room
 http://www.philips.de ▸ Bartender set
 http://www.vinspireuk.com/2014/12/cocktail-gifts-for-cocktail-lovers.html ▸ Mojito ingredients
 https://www.nelleulla.com/lv-en/products/truffles/4-mojito-truffle ▸ Mockito Mojito
 http://www.seedylawyer.com/history-of-hemingways-mojitos/ ▸ Raspberry Mojito
 http://goodpixcool.com/raspberry+mojito+in+a+bottle?image=99002602 ▸ Drinking Mojito
 https://www.lancerskincare.com/blog/10-ways-to-age-your-skin-prematurely/
  86. @MOLSJEROEN MANY THANKS ▸ Jeroen Mols (Belgium) ▸ @MolsJeroen ▸

    http://jeroenmols.com/blog