Introduction to Kotlin for Android Developers

At Google I/O 2017, the Android team at Google announced Kotlin as the official language for Android development. With this update, Android developers can now enjoy the features of a more modern programming language. That said, Android developers are not forced to used Kotlin and can keep using Java which is still supported.

Why using Kotlin?

  • Interoperability: Kotlin is a JVM base language, it is fully ‘inter-operable’ with Java. This means we can have Kotlin code can co-exist with Java code and vice versa.
  • Kotlin is a programming language developed by JetBrains, same company who developed IntelliJ. Android Studio IDE is based on IntelliJ.framework.
  • Modern programming language fully supported. All the features of Java 1.8 are not available when developing using Android SDK (if need to support lower version of Android).
  • Safer: Deal with null pointer at compile time. Preventing null pointer exceptions is much easier.
  • Expressiveness: Kotlin will in many case involve writing less code for solving same problem.

Before going deeper into these new features, lets start from basic.

 

Variables

Mutable Object

In Java, we would have following code to represent a mutable object of type String

String mObject = "Hello World";

 

This would be the equivalent in Kotlin:

var mObject: String = "Hello World"
  • The “var” keyword is used for mutable type object.
  • The type of the object (String) is specified before its name (mObject) You can think of it as mObject “extends” String. (e.g, mObject: String )
  • Semi-colon is optional in Kotlin.

Inferred Type

However, we can simplify the code as Kotlin can automatically Infer type of the object. Kotlin can infer the type of the object based on the value which it is set to. For example, since we are assigning the string “Hello” to the object, we don’t need to specify its Type:


var mObject = “Hello”

If now, we instead integer value “10”,  Kotlin will infer the Type of the object as Int


var mObject = 10

 

Immutable Object

An immutable object is one whose value is set once and cannot be changed. In Java, we are used to the keyword “final” to describe an immuatable object:


final String MOBJECT = "Hello World";

The “val” keyword is used to describe a immutable in Koltin:


val contantObject = "Hello World"

The general good practice is to always use immutable as far as possible. This makes code more predictable and will be important when working with Null safety feature which we will look into the next section.

 

Null safety feature

A common crash in many programming languages (including Java) is when accessing an attribute or method of a null reference. In Java this would result in a crash equivalent of a NullPointerException (NPE).  This error is also known as The Billion Dollar Mistake.

Kotlin’s type system is designed to prevent NullPointerExceptions.


val strOptional: String? = null

strOptional?.length

This is equivalent to following in Java:


if (strOptional != null)

    strOptional.length()

strOptional?.length: If and only if the object strOptional is not null, will the length method be call

Note that the “?” is required for the code/project to compile. We can use not-null assertion operator (!!) as below to force the code to compile, however in the above scenario, it would result in a NPE.


strOptional!!.length

 

Classes

Classes in Kotlin are declared using keyword class. We will create a Class which extends Activity from Android SDK.


class MainActivity: Activity {}

This would be equivalent of following in Java:


final class MainActivity extends Activity {}

Classes are closed by default which is equivalent of “final” in Java. So we won’t be able to extend the class “MainActivity” in another class. To make the class extendable, we have to explicitly declared class as open or abstract:

open class BaseActivity: Activity {}

MainActivity can extend BaseActivity of if BaseActivity class is “open”:

class MainActivity: BaseActivity {}

 

Data classes & Properties

Kotlin provide Data type classes and Properties which avoid many boilerplate which would be required in Java which creating POJO classes. Properties are equivalent to fields in Java but which includes getters and setters. However in Kotlin, we don’t need to explicitly declare getters and setters, it will be automatically created under the hood.

Let’s say we have a User model which requires the following attributes (properties in kotlin): “firstName” and “surname

public class User {
    private String firstName;
    private String surnameName;
    private String mood;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getSurnameName() {
        return surnameName;
    }

    public void setSurnameName(String surnameName) {
        this.surnameName = surnameName;
    }

    public String getMood() {
        return mood;
    }

    public void setMood(String mood) {
        this.mood = mood;
    }
}

We can have the above class with only 1 line in Kotlin by using “data” class  contain firstName and lastName properties:

 data class User(val firstName: String, val lastName: String, val mood:String) 

Kotlin will generate the generic getters and setters methods under the hood for properties. That will allow us to write less and also make it easier to manage changes.

 

Instantiating an object

When instantiate an object in Kotlin, we don’t need to specify the “New” keyword each time as in Java:


val user = User("Frank", "Einstein", "happy")

 

Data classes come with some  handy functions:

  • copy() -> This is handy if we are using immutable objects.

A general practice is to use immutable objects when possible to avoid unexpected changes from other part of our code. e.g,


val user = User("Frank", "Einstein", "happy")

val userUpdated = user.copy(mood = "angry")

  • equals() -> compare all properties of object to another to make sure they are identical:
user.equals(userUpdated) // false since Frank's mood has changed

 

Functions

Let’s create a small function which takes two integers and return their sum in Java:


private void sum(int x, int y) {
    return x + y;
}

In Kotlin, functions are declared using the “fun” keyword. Parameters will be

fun sum(x: Int, y: Int): Int {
   return x + y
}

Note that for the parameter X or Y, we write the Name first, then its Type. The return type (Int) is at the end just before function body.

If the result can be calculated in a single expression we can omit the curly braces and simply specify the function body after “=” symbol as below:

fun sum(x: Int, y: Int): Int = return x + y

 

Higher-order function

Functions are first class citizen in Kotlin, which means function can be passed as variable, arguments or return from other functions. We will store same sum function into an object using lambda expressions as below:

val sum = { x: Int, y: Int -> x + y }
  • A lambda expression in Kotlin is surrounded by curly braces {}
  • the code before the “->” sign x: Int, y: Int  is parameter declaration for our function
  • the code after the “->” sign is the body of the function
  • the return type is automatically inferred with Kotlin as we already know the parameter is of type int, the expression will return and Int

 

Extension Function

Another interesting feature with Kotlin (and other modern programming language) is Extension function. If you are new to this concept, I will try to explain you the concept by using components from Android SDK.

Imagine you want to have a method for all your Activity classes. In Java, we would create a “BaseActivity” class which will have the required method implementations, and then have all of our activities extend that BaseActivity and inherit the method. Kotlin provides a special feature known as Extension Function. Instead of base calls, a static method will be created and made available to the existing Activity class from the Android SDK:

fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, duration).show()
}
  • Note parameter default value is used for Duration parameter: duration: Int = Toast.LENGTH_SHORT
  • “this” -> refers to the Activity itself. Inside of the Extension we will have all methods which are accessible from the Activity class. For e.g getApplicationContext().

 

That works like magic. The extension function can be written anywhere in our project. I understand Kotlin basically generates a static method which is made available to actual Activity class:

class MainActivity : Activity(), MainContract.View {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        toast("this is toast from extension function")
    }

}

Extension function is very useful if we want to add a function into a code base which we cannot modify class inside of Library and Android SDK.

The Kotlin team developed a robust library for Android which implements many useful extension functions: https://github.com/JetBrains/anko which basically “adds” new features to Android Framework. It might be worth looking into.

 

Conclusion

Kotlin is similar to Java, it runs on JVM and is fully supported by Android Studio. I would say it’s a must for Android developers to give it a try. There are indeed many new features some which I covered in this blog post. I hope this is helps you started to get into Kotlin language. In future blog posts, I may go deeper inside specific features which I find useful. You can always  keep in touch by clicking on “Follow” button at the bottom right corner. Stay blessed. Cheers

Intro to Room Persistence Library

In almost every mobile app, we need to cache/save data on the client side. You want your data to be saved in a reliable and most manageable way.

In Google I/O 2017, Google introduced Room persistence layer which is an abstraction layer over SQLite. Essentially, it would allow you to map java objects into SQLite tables/fields instead of having to write complex SQL/SQLite boilerplates. A lot of useful third party abstraction like GreenDao, Ormlite were already available before that. However, if you need an “SQL” based database on Android, Room is probably the most reliable solution now. (If you don’t need SQL based, e.g, you have few or no relationship, you can check Realm mobile database)

Without further due, let see how we can use this new Library which comes in-built with Android SDK latest version.

So, you will have to set the Compile SDK to latest version in your app.gradle:

compileSdkVersion 26

Add Room Dependencies

compile 'android.arch.persistence.room:runtime:1.0.0-alpha8'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0-alpha8'

Annotate a model as Entity

Using annotation you can persist any of your models to Room.

@Entity
public class User {

    @PrimaryKey
    private String userId;

    private String firstName;
    private String lastName;
    private String nickname;
}

We added 2 annotations “Entity” for the Model which we want to persist, we also need to specify the “Primary key” with any one field. So far so good.

Create DAO interface

This is where you define the list of methods (operations) which can be done on your entity. If you have used, “Retrofit”, it is similar to API service where we define all API methods. Room also uses Annotations for us to define list of operations which we can perform on the object. E.g, we want to insert/delete a User object.

@Dao
public interface UserDao {
    @Insert
    void insert(User item);

    @Insert
    void insertAll(List<User> items);

    @Delete
    void delete(User item);

    @Query("DELETE FROM user")
    void deleteAll();

    @Query("SELECT * FROM user")
    List<User> getListUser();
}

We can use “Insert” and “Delete” annotations for inserting and deleting. To fetch users data from DB, we will need to use “Query”. We will have to write a small SQL but the good thing here is that Room will tell you if there is any error in your SQL at compile-time.

Create app Database class

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {

    private static AppDatabase INSTANCE;

    public static AppDatabase getDatabase(Context context) {
        if (INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "app_database")
                    .allowMainThreadQueries() // Avoid calling main thread if large dataset
                    .fallbackToDestructiveMigration() // Add custom migration when needed
                    .build();
        }
        return INSTANCE;
    }

    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            // Since we didn't alter the table, there's nothing else to do here.
        }
    };

    public static void destroyInstance() {
        INSTANCE = null;
    }
    public abstract UserDao userDao();
}

You can create a static instance of your Database inside you Application class

AppDatabase.getDatabase(context);
UserDao userDao = AppDatabase.getDatabase(context).userDao();

Or if you are using Dagger 2:

@Module
public class DatabaseModule {

    public DatabaseModule() {}

    @Singleton
    @Provides
    public AppDatabase getDBInstance(Context context) {
        return AppDatabase.getDatabase(context);
    }

    @Singleton
    @Provides
    public UserDao getUserDao(Context context) {
        return getDBInstance(context).userDao();
    }
}

UserDao – Insert/Delete/Select User objects

userDao.insert(new User());

We can access all of the methods we have defined inside UserDao interface so that we save or get data to/from Room Database.

Note that I have allow transactions on Main Thread (“allowMainThreadQueries” inside AppDatabase class). However if you have bigger database transaction, e.g, you can use “RxJava” for threading.

This was a basic introduction to Room to get started. We haven’t used any relationship and we are only storing one table. Something to lookup to maybe in another blog post. If you have any queries, please let me know. Enjoy!! Happy coding!!!

Regards,

Retrofit – Generic Error Handling and custom exception messages

Retrofit is an HTTP client for Android and Java written by Square Inc.

Today I want to expose a way to handle network exceptions for all your service calls and creating your generic error  messages in a simple way when using Retrofit.

 

GenericException class

We will create a GenericException class where we will put all the types which we want to catch and their corresponding error messages we want to display. SocketException, and I have created a custom exception: InternalServerError. Please find below the code for the GenericException class:

public class GenericException extends IOException {
    Context context;
    String message;

    public GenericException(Context context, Exception e) {
        this.context = context;
        message = context.getString(R.string.str_internet_connection_error);

        if (e instanceof SocketException) {
            message = context.getString(R.string.str_internet_connection_error);

        } else if (e instanceof InternalServerError) {
            message = context.getString(R.string.str_internal_server_error);
        }
    }

    @Override
    public String getMessage() {
        return message;
    }
}

class InternalServerError extends IOException {}

OkHttpClient – Request Interceptor

Retrofit uses OkHttpClient which allows you to add an “interceptor” method. This will allow you to intercept all requests made on your retrofit services. As a result, you can make (common) changes to your requests (e.g add Auth Token) and also inspect the corresponding response and status code.

Below is a code snippet is interceptor method on the Network Module. Notice that we are throwing error using instance of our GenericException class. These exceptions will be propagated to the Activities (or presenter) where the services requests were made.

I checked for 500 status code on the response to catch Internal Server Error and to throw our custom Internal Server Error which will use the custom Exception Message. We also have SocketException to handle timeout exceptions for no internet connection scenarios.

@Singleton
@Provides
public APIService getService(Context context, OkHttpClient.Builder httpClient, Retrofit.Builder retrofit) {
    httpClient.addInterceptor((Interceptor.Chain chain) -> {

        if (!NetworkUtils.isNetworkAvailable(context)) {     // Check if there is internet connection
            throw new GenericException(context, new SocketException());
        }

        Request originalRequest = chain.request();
        // set OAuth token
        Request.Builder newRequest = originalRequest.newBuilder();
        String accessToken = SharedPreferencesRepository.getAuthToken(context);

        newRequest.header("Content-Type", "application/json");
        newRequest.header("Accept", "application/json");
        newRequest.header("Authorization", "Bearer " + accessToken).method(originalRequest.method(), originalRequest.body());

        originalRequest = newRequest.build();

        Response response = chain.proceed(originalRequest); //perform request, here original request will be executed
        int responseCode = response.code();

        if (responseCode == 500) {   // Check for Internal Server errors
            throw new GenericException(context, new InternalServerError());    // Internal Server Error
        }

        if (responseCode == 401) { . // Expired or invalid Auth Token

            // Unauthorized. E.g, Token Expired
            // refreshToken service call
            .
            .
            .
        }

        return response;
    });

    retrofit
        .baseUrl(baseUrl)
        .client(httpClient.build())
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

    return retrofit.build().create(APIService.class);
}

 

Propagating exception message to the UI

If you are using Rx Java, you will have something as below. The method (Throwable e) will get called whenever there is an exception thrown from the apiService. Exception messages which were defined on the GenericException class are thrown to (Throwable e) method. The exception message “e.getMessage()” can now be displayed to the users, e.g, on an AlertDialog.

Subscription s = apiService.loginRequest(userLoginRequest)
    .compose(RxUtils.applySchedulers())
    .subscribe(
        (UserLoginResponse userLoginResponse) -> {  // on Success
            mView.hideLoading();
            if (userLoginResponse.isSuccess()) {
                mView.onLoginSuccessful();

            } else
                new Throwable(context.getString(R.string.str_login_invalid_credentials));
        },
        (Throwable e) -> { // on Fail

            mView.onLoginFailed(e.getMessage()); // Display exception on an AlertDialog
            mView.hideLoading();
        },
        () -> { // on Complete
            mView.hideLoading();
        });

 

Looking forward for next posts. Let me know if you have any queries or if you want me to share additional codes.

Cheers,

Android Design Patterns – MVP, DI using Dagger and Unit Testing

Design Patterns

Various Android Design Patterns can be used to enhance your android code base: among those MVC, MVVM, Reactive, MVP.

The goal of design pattern is to make your code and project more:

  1. Scalable
  2. Maintainable
  3. Testable

Using Standards Design patterns will make you more valuable as a developer. It will help you to work better in a team. Learning and applying patterns will also make you more adaptable to other frameworks.

Clean architecture/MVP pattern and unit testing are practices which helped me improve my code quality and to develop maintainable apps. In the process of applying a new pattern, you will be learning new techniques which you may apply in other places of your code base as well. The MVP pattern can have a slower learning curve than using “classic” android architecture where you have Activities/Fragments which act like a “ViewController” and contain mix of UI and Business logics. But in long run, using classic android does not bring much Pros compared to other design patterns.

Intro to MVP Pattern – with Example

MVP stands for Model-View-Presenter architectural pattern. It is a derivative of Model View Controller and is a more popular architecture.

Model-View-Presenter, the View are our Activities or Fragments which will contain only UI update logics. All logics which depends on Android SDK and related to UI will remain in View (Fragment or Activity). The “Presenter” will contain all business logics. Presenter will communicate to the “View” through interfaces (e.g to send data for the View to display on the User Interface). The Presenter layer should not include any Android SDK specifics implementations. The Presenter logic can be fully tested with JUnit tests. Model will include repositories and all data types we have to manipulate on the app.

Let’s look at simple Logic example to get basic concern. The example includes usage Dagger 2 and Rx Java.

(For more on Dagger 2, please check my blog post: https://devanshramen.com/2017/08/23/explaining-dependency-injection-with-dagger-2-android/ )

 

First thing, we need define a “Contract” which is basically an Interface which will define all the required methods on the View and the Presenter.

LoginContract

public interface LoginContract {

    interface View extends BaseContract.BaseView {

        void onLoginSuccessful();

        void onLoginFailed(String strError);

        void onErrorEmptyEmail();

        void onErrorInvalidEmail();

        void onErrorEmptyPassword();

    }

    interface Presenter extends BaseContract.BasePresenter {

        void callLoginAPI(UserLoginRequest userLogin);

        boolean validateLoginInputs(UserLoginRequest userLogin);
    }
}

 

In this example, we have a client-side validation to check for empty/invalid email, and password and finally and API call to Login Service. The validation logic, will be implemented inside the “validateLoginInputs(UserLoginRequest userLogin)” method which will be implemented by Presenter.

The Fragment will implement the View so as to implement the display error or success UI updates. The Presenter will be trigger UI update by calling the corresponding “View” methods. E.g, onErrorInvalidEmail() will display a hint message stating user’s have input an invalid email.

Below are implementations for LoginPresenter and LoginFragment:

LoginPresenter

/**
 * Created by devanshramen on 4/17/17.
 * @author devansh
 */

public class LoginPresenter extends BasePresenter implements LoginContract.Presenter {

    @NonNull
    LoginContract.View mView;

    public LoginPresenter(@NonNull LoginContract.View mView) {
        super(mView);
        this.mView = mView;
    }
    
    // Client validation
    @Override
    public boolean validateLoginInputs(UserLoginRequest userLogin) {

        boolean isValid = true;

        if (userLogin.getEmail().length() <= 0) {
            mView.onErrorEmptyEmail();
            isValid = false;
        }

        if (!EmailUtils.isValidEmail(userLogin.getEmail())) {
            mView.onErrorInvalidEmail();
            isValid = false;
        }

        if (userLogin.getPassword().length() <= 0) {
            mView.onErrorEmptyPassword();
            isValid = false;
        }
        return isValid;
    }

    @Override
    public void callLoginAPI(UserLoginRequest userLoginRequest) {

        mView.showLoading();

        Subscription s = apiService.loginRequest(userLoginRequest)
            .compose(RxUtils.applySchedulers())
            .subscribe(
                (UserLoginResponse userLoginResponse) -> {  // on Success

                    mView.hideLoading();
                    LogUtils.showLogInfo(userLoginResponse.toString());

                    if (userLoginResponse.isSuccess()) {
                        appSessionRepository.setFirstTime(true);
                        appSessionRepository.setLogin(true);

                        mView.onLoginSuccessful();

                    } else
                        new Throwable(context.getString(R.string.str_login_invalid_credentials));
                },
                (Throwable e) -> { // on Fail

                    if (e instanceof GenericException)
                        mView.onLoginFailed(e.getMessage());
                    else
                        mView.onLoginFailed(context.getString(R.string.str_login_invalid_credentials));

                    mView.hideLoading();
                },
                () -> { // on Complete
                    mView.hideLoading();
                });

        mSubscriptions.add(s);
    }
}

LoginFragment

/**
 * Created by devanshramen on 4/17/17.
 * @author devansh
 */

public class LoginFragment extends BaseFragment implements LoginContract.View {

    @Bind(R.id.edt_username)
    EditText edtUsername;

    @Bind(R.id.edt_password)
    EditText edtPassword;

    @Bind(R.id.txt_no_username_error)
    TextView txtInvalidUsername;

    @Bind(R.id.txt_invalid_password)
    TextView txtInvalidPassword;

    LoginActivity activity;

    private LoginContract.Presenter mPresenter;

    public LoginFragment() {
        // Required empty public constructor
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    protected int getResourceLayout() {
        return R.layout.fragment_login;
    }

    @Override
    protected void onViewReady(Bundle savedInstanceState) {
        initViews();
    }

    private void initViews() {
        mPresenter = new LoginPresenter(this);
        activity = (LoginActivity) getActivity();
    }

    @OnClick(R.id.btn_login)
    public void onClickBtnLogin() {

        UserLoginRequest userLogin = new UserLoginRequest();
        userLogin.setEmail(edtUsername.getText().toString());
        userLogin.setPassword(edtPassword.getText().toString());

        txtInvalidUsername.setVisibility(View.INVISIBLE);
        txtInvalidPassword.setVisibility(View.INVISIBLE);

        if (mPresenter.validateLoginInputs(userLogin)) {
            KeyboardUtils.hideKeyboard(getActivity());
            mPresenter.callLoginAPI(userLogin);
        }
    }

    @OnClick(R.id.txt_forget_password)
    public void onClickTxtForgetPassword() {
        ActivityUtils.openActivity(getContext(), ResetPasswordActivity.class,"");
    }

    @Override
    public void onLoginSuccessful() {
        ActivityUtils.openActivityAndFinish(getActivity(), MainDrawerActivity.class, "login");
    }

    @Override
    public void onLoginFailed(String strError) {
        dialogUtils.showDialogBox(getString(R.string.str_error_dialog), strError);
    }


    @Override
    public void onErrorEmptyEmail() {
        txtInvalidUsername.setText(getString(R.string.str_login_username_error_empty));
        txtInvalidUsername.setVisibility(View.VISIBLE);
    }

    @Override
    public void onErrorInvalidEmail() {
        txtInvalidUsername.setText(getString(R.string.str_login_username_error_invalid));
        txtInvalidUsername.setVisibility(View.VISIBLE);
    }

    @Override
    public void onErrorEmptyPassword() {
        txtInvalidPassword.setVisibility(View.VISIBLE);
    }
}

BasePresenter & Dependency Injection with Dagger 2

You may have noticed that our LoginPresenter is extending BasePresenter. In these Base classes, we have common initialization methods e.g Database, RxJava stuffs we will put in itself BasePresenter.

public class BasePresenter implements BaseContract.AppBasePresenter {

    @Nonnull
    BaseContract.AppBaseView mView;

    @NonNull
    protected CompositeSubscription mSubscriptions;

    @Inject
    protected APIService apiService;

    @Inject
    protected Context context;

    @Inject
    protected ProfileRepository profileRepository;

    public BasePresenter(@Nonnull BaseContract.AppBaseView mView) {
        this.mView = mView;

        MApplication.getAppComponent().inject(this); // DI using Dagger

        mSubscriptions = new CompositeSubscription();

        LogUtils.showLogDebug("subscribe");
    }

    @Override
    public void subscribe() {

    }

    @Override
    public void unSubscribe() {
        mSubscriptions.clear();
    }
}

We are using Dagger 2 here as our Dependency Injection framework. (For more about Dagger 2: Please check http://www.vogella.com/tutorials/Dagger/article.html) which describes it in enough details.

Unit Testing

We will also want to have Unit Tests on the Presenter such that we can check if we are implementing the right/expected business logic and also the right “UI” method is being called by the Presenter:

@RunWith(MockitoJUnitRunner.class)
public class LoginPresenterTest extends TestCase{

    @Mock
    private LoginPresenter mPresenter;

    @Mock
    private LoginContract.View mView;

    @Mock
    SessionRepository appSessionRepository;

    private UserLoginRequest userLogin;

    @Before
    public void setUpTesting() throws Exception{
        MockitoAnnotations.initMocks(this);

        mPresenter = new LoginPresenter(mView);
    }

    @Test
    public void testEmptyUsername() throws Exception {
        //test case passed - Data missing
        userLogin = new UserLoginRequest("", "xxx");
        mPresenter.validateLoginInputs(userLogin);
        verify(mView).onErrorEmptyEmail();
    }


    @Test
    public void testEmptyPassword() throws Exception {
        //test case passed - Data missing
        userLogin = new UserLoginRequest("xxx@xxxx.com", "");
        mPresenter.validateLoginInputs(userLogin);
        verify(mView).onErrorEmptyPassword();
    }

    @Test
    public void testValidUsernamePassword() throws Exception {
        //test case passed - Data missing
        userLogin = new UserLoginRequest("xxx@xxxx.com", "xxxx");
        assertTrue(mPresenter.validateLoginInputs(userLogin));
    }

}

We are using Mockito to mock the Views. (Please check this link for more about Mockito: http://www.vogella.com/tutorials/Mockito/article.html). Note that we are only testing if the appropriate View methods are called, we can’t really check if it is correctly implemented on the View since the implementation contains Android SDK specific implementations and will not be testable using JUnit framework.

That’s all for today. Catch you soon with a new topic. Please leave a comments should this be helpful to you.

Best Regards

 

Refs:

– Google’s Sample