Issue
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?
Solution
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
Answered By - Anatolii
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.