Android Testing with JUnit & mockito

Tips, study notes, and mini-code samples

General Testing Tips

Verify Types

What is mock

What is stub

JUnit

How it operates

// Used for our preparation
@Before
public void setUp(){...}
// Used for the clean up
@After
public void tearDown(){...}

Testing Steps

How does JUnit @Rule work?

http://site.mockito.org

mockito framework

Why mockito is easy-to-use

How to start

dependencies {
...
testImplementation 'org.mockito:mockito-core:2.10.0'
}

Initializing mockito

/**
* As a runner,
* Which is not recommended if you are willing to use other runners
* beside mockito for testing
*/
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {...}
/**
* As a rule
*/
public class MyClassTest {
@Rule
MockitoRule mockitoRule = MockitoJUnit.rule();
...}

Verifying interactions

// Verifies this method called once
verify
(myMock).playMethod();
// Verifies this method called n number
verify
(myMock,times(3)).playMethod();
.............,atLeast(1).............
.............,atLeastOnce()..........
.............,atMost(1)..............
.............,only().................
.............,never()................
// Using Argument Matchers
verify(myMock).playMethod(anyString);
verify(myMock).playMethod(anyInt);
// If you used one matcher in one method argument, Rest of arguments of this methods needs to be matchers
verify(myMock).logout(anyString, eq(PASSWORD));
// Verify the call happen in specific order
InOrder inOrder = inOrder(myMock);
inOrder.verify
(myMock).login(); // First this one
inOrder.verify(myMock).logout(); // Thn this one

Stubbing methods

when(mockitoWebService.isOffline()).thenReturn(true);
/**
* This is not type safe
* You can use it if you are working with spies or Want to override * * previous stubbed method.
* Something you will rarely use
*/
doReturn(true).when(mockitoWebService).isOffline();
/* 
* Nothing different in functionality from Normal Syntax, Just
* written in a style like BDD
*/
given(mockitoWebService.isOffline()).willReturn(true);

Code example

// Default is false, We ask it to return true
when
(myWebServiceMock.isOffline()).thenReturn(true);
// Do the action
user.login()
// Verify the user never calls login if the device is offline
verify(myWebServiceMock.isOffline(), never()).login();
// Multiple return types, If I called first true, second false,...
when
(myWebServiceMock.isOffline()).thenReturn(true, false, true);

Capturing Arguments

Argument Captor

@captor
private ArgumentCaptor<Response> responseCaptor;
@Test
public void captureArguments() {
User user = new User (mockWebService, USER_ID, PASSWORD);
user.login(mockLoginInterface);
/**
* We are not verification here to check if the user called login on
* web-service. No, We are calling it to get a hold of parameters
* passed to the web-service.
* So, In this case we capture the response value passed by the user
* to the web-service
*/
verify(mockWebService).login(responseCaptor.capture());
Response response = responseCaptor.getValue();
// We pretend the network request was successful
response.OnRequestCompleted(true);
// And then check the user updates the UI accordingly
verify(mockLoginInterface).onLoginSuccess();
}

Advanced mockito

UI Testing

Testing data

public class TestUserData extends UserData {

@Override
public String getFirstName() {
return "FirstName";
}
@Override
public String getLastName() {
return "LastName";
}
@Override
public int getUserId() {
return 1111007;
}
}

New Creation

Public User(WebService webService, int user, String password){
this.webservice = webService;
...}
Public User(WebServiceFactory factory, int user, String password){
this.webservice = factory.createWebService();
...}

Android Engineer @eBay