尝试运行我的Espresso测试时,RecyclerViewMatcher中的NullPointerException

时间:2018-06-19 12:31:46

标签: android android-recyclerview android-espresso

我想在Espresso Testing上运行Android project

步骤1-找到我的RecyclerView

第2步,检查RecyclerView上的项目

第一步成功运行,但第二步应检查recycler view项目失败。.

这是我的测试:

    onView(withRecyclerView(R.id.recyclerView_recipes).atPosition(0))
                .check(matches(isDisplayed()));

        onView(withRecyclerView(R.id.recyclerView_recipes).atPositionOnView(0, R.id.tv_recipe_name))
                .check(matches(isDisplayed()))
                .check(matches(withText("Nutella Pie")));

这是我的适配器:

package com.example.android.advancebakingapp.Adapter;


import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.android.advancebakingapp.Activity.RecipeFragment;
import com.example.android.advancebakingapp.MainActivity;
import com.example.android.advancebakingapp.Model.Ingredient;
import com.example.android.advancebakingapp.Model.Recipe;
import com.example.android.advancebakingapp.R;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.List;

public class RecipeAdapter extends
        RecyclerView.Adapter<RecipeAdapter.RecipeAdapterViewHolder> {
    private Context context;
    private ArrayList<Recipe> mRecipes;
    private RecipeOnClickHandler mRecipeOnClickHandler;

    public static final String INGREDIENTS = "mIngredients";
    public static final String INGREDIENTS_BUNDLE = "ingredientsBundle";
    
    public RecipeAdapter(RecipeOnClickHandler recipeOnClickHandler) {
        mRecipeOnClickHandler = recipeOnClickHandler;
    }

    public void setRecipesData(ArrayList<Recipe> recipeData) {
        mRecipes = recipeData;
        notifyItemRangeChanged(0, mRecipes.size());
       // notifyDataSetChanged();
    }


    @Override
    public RecipeAdapter.RecipeAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        // Inflate the custom layout
        View contactView = inflater.inflate(R.layout.row_recipe, parent, false);

        // Return a new holder instance
        RecipeAdapterViewHolder viewHolder = new RecipeAdapterViewHolder(contactView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecipeAdapter.RecipeAdapterViewHolder viewHolder, int position) {

        Recipe recipe = mRecipes.get(position);
        String imageUrl = mRecipes.get(position).getImage();
        TextView tv = viewHolder.mTextView;
        viewHolder.mIngredients = mRecipes.get(position).getIngredients();

        tv.setText(recipe.getName());

        if (imageUrl.equals("") && imageUrl.isEmpty())
        {
            Picasso.with(context).load(R.drawable.baking_app_ico).into(viewHolder.mImageView);
        }
        else
        {
            Picasso.with(context).load(imageUrl).into(viewHolder.mImageView);
        }

    }



    // Returns the total count of items in the list
    @Override
    public int getItemCount() {
        if(mRecipes == null) {
            return 0;
        }

        return mRecipes.size();
    }


    public class RecipeAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public final ImageView mImageView;
        public final TextView mTextView;
        private List<Ingredient> mIngredients;

        public RecipeAdapterViewHolder(View view) {
            super(view);
            mImageView = (ImageView) view.findViewById(R.id.iv_recipe_image);
            mTextView = (TextView) view.findViewById(R.id.tv_recipe_name);

            view.setOnClickListener(this);

        }

        @Override
        public void onClick(View view) {
            int position = getAdapterPosition();
            Recipe selectedRecipe = mRecipes.get(position);
            mRecipeOnClickHandler.onClickRecipe(selectedRecipe);
        }
    }

    public interface RecipeOnClickHandler {
        void onClickRecipe(Recipe recipe);
    }
}

现在,当我尝试运行测试时,出现此错误:

java.lang.NullPointerException: Attempt to read from field 'android.view.View android.support.v7.widget.RecyclerView$ViewHolder.itemView' on a null object reference
at com.example.android.advancebakingapp.RecyclerViewMatcher$1.matchesSafely(RecyclerViewMatcher.java:53)
at com.example.android.advancebakingapp.RecyclerViewMatcher$1.matchesSafely(RecyclerViewMatcher.java:26)
at org.hamcrest.TypeSafeMatcher.matches(TypeSafeMatcher.java:65)
at android.support.test.espresso.base.ViewFinderImpl$MatcherPredicateAdapter.apply(ViewFinderImpl.java:127)
at android.support.test.espresso.core.internal.deps.guava.collect.Iterators$5.computeNext(Iterators.java:639)
at android.support.test.espresso.core.internal.deps.guava.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:141)
at android.support.test.espresso.core.internal.deps.guava.collect.AbstractIterator.hasNext(AbstractIterator.java:136)
at android.support.test.espresso.base.ViewFinderImpl.getView(ViewFinderImpl.java:68)
at android.support.test.espresso.ViewInteraction$2.call(ViewInteraction.java:273)
at android.support.test.espresso.ViewInteraction$2.call(ViewInteraction.java:265)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

我尝试更改adapter ViewHolder,但失败。

这是我在GitHub上的项目: https://github.com/haya51033/AdvanceBakingApp 请帮忙?

1 个答案:

答案 0 :(得分:1)

尽管我的建议SystemClock.sleep(1000)为您效劳,但更多的是解决方法,而不是解决方案。真正的问题在于,当Espresso用文本断言视图时,它还不存在,因此睡眠会有所帮助。

一种更好的方法是使用RecyclerViewActions包中的espresso-contrib,因为它需要更多的时间来加载RecyclerView(它等待主循环空闲),因此您不需要自行实现(例如,放入SystemClock.sleep(...))。因此,您的测试可能如下所示:

onView(withId(R.id.recyclerView_recipes)).perform(RecyclerViewActions.actionOnItemAtPosition(0, isDisplayed())); 
onView(withId(R.id.recyclerView_recipes)).perform(RecyclerViewActions.actionOnItemAtPosition(0, Matchers.allOf(withText("Nutella Pie"), isDisplayed())));

有关更多信息,请在此处查看文档-

  

https://developer.android.com/training/testing/espresso/lists#recycler-view-list-items