Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Unit Testing: How to make a class more testable?

I have been developing android applications but didn't write any unit tests. Recently I started to learn about it and try to use JUnit to test my android applications.

I found that most of the times I get bugs in API calls, But I still can't understand how to write unit tests for them(& how to make the original code testable).

Let me explain the following function:

I am running a function call setOffenceList(). There are multiple actions happening inside the function.

i) Load the RestClient and pass the URL.

ii) RestClient talk to the JSON api and get the response

ii) I grab the response inside the onSuccess(String response) function

iii) Parse the JSON data and store inside an array

iv) If success I will show data in a list view (else show an error message)

This is the code:

public class OffenceFrag extends Fragment {


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.frag_offence, container, false);
        //run API call
        setOffenceList();
        return view;
    }

    private void setOffenceList() {
        String url = Paths.SITE_URL ;
        RestClient.get(url, null, new AsyncHttpResponseHandler() {

            @Override
            public void onStart() {
                Toast.makeText(getActivity(), "Loading offences...", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onSuccess(String response) {

                //Parse JSON
                JSONArray jsonArray;
                try {

                    JSONObject jsonObj = new JSONObject(response);
                    if(jsonObj.getString("status").equalsIgnoreCase("Success")){

                        jsonArray = new JSONArray(jsonObj.getString("data"));
                        if(jsonArray.length() > 0){
                            for (int i = 0; i < jsonArray.length(); i++) {

                                JSONObject row = jsonArray.getJSONObject(i);
                                OffenceORM off = new OffenceORM();
                                off.setOffenceId(row.getString("offence_id"));
                                off.setPhoto(row.getString("photo"));
                                off.setSubmittedBy(row.getString("submitted_by"));
                                offenceList.add(off);
                            }
                        }   

                        //Success: Show the list view
                        setOffenceAdapter();
                        Toast.makeText(getActivity(), "Successfully Loaded", Toast.LENGTH_LONG).show();

                    } else {
                        //Failed: show error message
                        Toast.makeText(getActivity(), "There are no offences submitted under project", Toast.LENGTH_LONG).show();
                    }

                } catch (Exception e) {
                    Log.e("exception", e.getMessage());
                }
            }

            @Override
            public void onFailure(Throwable error, String content) {
                Log.e("failed", error.getMessage());
            }

            @Override
            public void onFinish() {

            }
        });
    }


}//end

I can't really understand how can I write a test function to something like the above code.

Can you please show me how to break down this code to testable pieces and write unit test functions to them?

Thanks a lot!

like image 339
stackflow Avatar asked Jan 26 '16 10:01

stackflow


People also ask

Does unit test increase code quality?

Good unit tests create testable code, which improves quality. That code will have fewer defects, which means fewer bug fixes, for faster project completion.


1 Answers

Only and only a good design can help you making Unit testing easier. That's why Test Driven Development is there. So that you can not go with wrong design.

When you unit test you simply test code written by you and use mock objects provided by Android to test android Api calls.

As far as other Api have issues than its the issue of Api developer not yours. You can use mock framework like Mockito to test functionality of your code when it make call to other API code. Test API code separately if you are developing your own API.

Design principles must be followed for good design like

  • S – Single-responsiblity principle
  • O – Open-closed principle
  • L – Liskov substitution principle
  • I – Interface segregation principle
  • D – Dependency Inversion Principle

Important Points:

  • one assert method call per unit test case
  • Don't modify classes just for testing.
  • Use of interfaces
  • Do not put too many statements or functionality in one method.
  • Don't make too big classes.
  • Use TDD.......Many more

Unit testing a badly design code is complete wastage. As test will break every time you make some changes to classes. In Android this will happen even more. As you are stuck with Android life cycle methods.

Carefully abstract away functionality that you want to test in their own classes.

This will make your application code more robust, simple and clear.

like image 62
abcdef12 Avatar answered Oct 19 '22 19:10

abcdef12