NullPointerException in RecyclerViewMatcher when try run my Espresso Test

一曲冷凌霜 提交于 2021-01-27 12:20:22

问题


I want to run Espresso Testing on my Android project

Step 1- Find my RecyclerView

Step 2- check an Item on the RecyclerView

The first Step ran Successfully, but the second which should check the recycler view Item Failed..

This is my test:

    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")));

and this is my Adapter:

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);
    }
}

Now when I try to run my test, I have this Error:

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)

I tried to change my adapter ViewHolder but it failed.

This is my project in GitHub: https://github.com/haya51033/AdvanceBakingApp Please help?


回答1:


Even though my suggested SystemClock.sleep(1000) worked for you it's more of a workaround than a solution. The real problem here is that at a time when Espresso asserts the view with the text it's not there yet and so the sleep helps.

A better approach is to use RecyclerViewActions from the espresso-contrib package because it waits a bit more for your RecyclerView to load(it waits until the main loop is idle) and thus you don't need to implement it yourself (for instance, to put SystemClock.sleep(...)). So, your test could look like this:

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())));

For more information please check the doc here -

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



来源:https://stackoverflow.com/questions/50928535/nullpointerexception-in-recyclerviewmatcher-when-try-run-my-espresso-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!