$30 off During Our Annual Pro Sale. View Details »

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.

Jeroen Mols

June 16, 2016
Tweet

More Decks by Jeroen Mols

Other Decks in Programming

Transcript

  1. TESTING MADE SWEET
    WITH A MOCKITO
    @MOLSJEROEN

    View Slide

  2. @MOLSJEROEN
    @MOLSJEROEN

    View Slide

  3. IF YOU DON’T LIKE UNIT TESTING YOUR
    PRODUCT, MOST LIKELY YOUR CUSTOMERS
    WON’T LIKE TO TEST IT EITHER.
    Unknown

    View Slide

  4. ALWAYS WRITE A TEST TO REPRODUCE A
    BUG BEFORE YOU FIX IT
    Robert C. Martin*

    View Slide

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

    View Slide

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

    View Slide

  7. WAY OF WORKING

    View Slide

  8. @MOLSJEROEN
    TEST REQUIREMENTS
    ▸ All tests must
    ▸ Run really fast
    ▸ Be small and focussed
    ▸ Reliable, not “flaky”
    ▸ Challenges: UI & WebService
    UI
    USER
    WEBSERVICE

    View Slide

  9. @MOLSJEROEN
    SOLUTION
    ▸ Isolate User
    ▸ Don’t include UI
    ▸ Replace WebService with dummy
    ▸ Mimic WebService behaviour
    ▸ => Verify interactions
    UI
    USER
    WEBSERVICE*

    View Slide

  10. @MOLSJEROEN
    DEFINITION: TEST DOUBLES
    ▸ Replace real class
    ▸ Same interface
    ▸ Different behaviour
    WEBSERVICE*
    WEBSERVICE
    public void login() {

    // NORMAL IMPL.

    }
    public void login() {

    // DO NOTHING

    }

    View Slide

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

    // NORMAL IMPL.

    }
    public void login() {

    // DO NOTHING

    }

    View Slide

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

    // NORMAL IMPL.

    }
    public void login() {

    loginInterface.success();

    }

    View Slide

  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();

    }

    View Slide

  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

    View Slide

  15. MOCKITO

    View Slide

  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?

    View Slide

  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

    View Slide

  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"

    }

    View Slide

  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"

    }

    View Slide

  20. INGREDIENTS

    View Slide

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

    View Slide

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

    View Slide

  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);

    }

    View Slide

  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);

    }

    View Slide

  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);

    }

    View Slide

  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);

    }

    View Slide

  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);

    }

    View Slide

  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);

    }

    View Slide

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

    View Slide

  30. @MOLSJEROEN
    VERIFYING INTERACTIONS
    @Test

    public void verifyInteractionTimes() throws Exception {

    User user = new User(mockWebService, USER_ID, PASSWORD);


    user.logout();


    verify(mockWebService).logout();

    }

    View Slide

  31. @MOLSJEROEN
    VERIFYING INTERACTIONS
    @Test

    public void verifyInteractionTimes() throws Exception {

    User user = new User(mockWebService, USER_ID, PASSWORD);


    user.logout();


    verify(mockWebService).logout();

    }

    View Slide

  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()

    }

    View Slide

  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!

    View Slide

  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);

    }

    View Slide

  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)

    }

    View Slide

  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

    View Slide

  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)

    }

    View Slide

  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}")
    }

    View Slide

  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

    View Slide

  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();

    }

    View Slide

  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();

    }

    View Slide

  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();

    }

    View Slide

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

    View Slide

  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();

    }

    View Slide

  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();

    }

    View Slide

  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();

    }

    View Slide

  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();

    }

    View Slide

  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();

    }

    View Slide

  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);

    View Slide

  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);

    View Slide

  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);

    View Slide

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

    View Slide

  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

    View Slide

  54. @MOLSJEROEN
    CAPTURING ARGUMENTS
    @Captor

    private ArgumentCaptor responseArgumentCaptor;
    UI USER WEBSERVICE
    LOGININTERFACE RESPONSE

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  60. @MOLSJEROEN
    MOCKITO LIMITATIONS
    ▸ Unable to mock
    ▸ final classes
    ▸ final methods
    ▸ static methods
    ▸ private methods
    ▸ hashCode() and equals()

    View Slide

  61. ADVANCED MOCKITO

    View Slide

  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

    View Slide

  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"

    }

    View Slide

  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"

    }

    View Slide

  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"

    }

    View Slide

  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

    }

    }

    View Slide

  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

    }

    }

    View Slide

  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);

    }

    }

    View Slide

  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);

    }

    }

    View Slide

  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);

    }

    }

    View Slide

  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();

    }

    }

    View Slide

  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();

    }

    }

    View Slide

  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

    }

    View Slide

  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";

    }

    ...
    }

    View Slide

  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";

    }

    ...
    }

    View Slide

  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

    View Slide

  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

    View Slide

  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;

    }

    View Slide

  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();

    }

    View Slide

  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”

    View Slide

  81. WRAP UP

    View Slide

  82. IT IS BETTER TO HAVE A SIMPLE TEST
    THAT WORKS THAN A COMPLICATED
    TEST THAT SEEMS TO WORK.
    Mockito documentation

    View Slide

  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

    View Slide

  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

    View Slide

  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/

    View Slide

  86. @MOLSJEROEN
    MANY THANKS
    ▸ Jeroen Mols (Belgium)
    ▸ @MolsJeroen
    ▸ http://jeroenmols.com/blog

    View Slide