提问者:小点点

Android单元测试:如何使类更具可测试性?


我一直在开发android应用程序,但没有编写任何单元测试。最近我开始了解它,并尝试使用JUnit来测试我的android应用程序。

我发现大多数时候我在API调用中得到bug,但我仍然无法理解如何为它们编写单元测试(

让我解释一下以下功能:

我正在运行一个函数调用setOffenceList()。函数内部发生了多个操作。

i)加载RestClient并通过URL。

ii)RestClient与JSONapi对话并获得响应

ii)我在on成功(字符串响应)函数中获取响应

解析JSON数据并存储在数组中

iv)如果成功,我将在列表视图中显示数据(否则显示错误消息)

这是代码:

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

我无法真正理解如何为上述代码编写测试函数。

你能告诉我如何将这些代码分解为可测试的部分并为它们编写单元测试函数吗?

非常感谢!


共3个答案

匿名用户

只有好的设计才能帮助您简化单元测试。这就是测试驱动开发存在的原因。这样你就不会使用错误的设计。

当您进行单元测试时,您只需测试您编写的代码,并使用Android提供的模拟对象来测试android Api调用。

至于其他Api有问题比它的问题Api开发者不是你的。你可以使用模拟框架,如Mockito来测试你的代码的功能,当它调用其他API代码时。如果你正在开发自己的API,单独测试API代码。

良好的设计必须遵循设计原则,例如

  • S

要点:

  • 每个单元测试用例调用一个assert方法
  • 不要仅仅为了测试而修改类。
  • 接口的使用
  • 不要在一个方法中放置太多语句或功能。
  • 不要上太大的课。
  • 使用TDD更多

单元测试一个糟糕的设计代码是完全浪费。因为每次您对类进行一些更改时,测试都会中断。在Android中,这种情况会发生得更多。因为您被Android生命周期方法卡住了。

仔细抽象出您想要在他们自己的类中测试的功能。

这将使您的应用程序代码更加健壮、简单和清晰。

匿名用户

你在片段中做了太多的事情,很难测试和维护。

我在我的项目中使用MVP模式,它允许将表示层与逻辑分开,避免将所有代码放在片段/活动中。

查看本文:http://antonioleiva.com/mvp-android/

以及GitHub中相应的代码示例:https://github.com/antoniolg/androidmvp

匿名用户

罗希特·卡特卡尔使用TDD的建议当然值得你在开发下一段代码时考虑。但是,现在这段代码已经存在,你在问“如何将这段代码分解成可测试的部分”:你可以首先忽略可测试性,试着将这段代码分解成更小的部分:扩展类定义和拆分方法,就像优化一般的易读性一样。你已经会发现一些冗余(围绕for循环的if)。

结果是,每个生成的方法对其他类的依赖都可能更少。然后,您可以专注于减少这些依赖关系。查看Michael Feather关于处理遗留代码的书,了解一大堆打破依赖关系的方法。编辑:有人提取了一系列打破依赖关系的技术(尽管只是高级描述):http://rubyexperiences.blogspot.de/2005/12/dependency-breaking-techniques-from.html