首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在片段中使用Espresso测试回收器视图使用IdlingResource截取数据

如何在片段中使用Espresso测试回收器视图使用IdlingResource截取数据
EN

Stack Overflow用户
提问于 2017-06-01 23:53:38
回答 1查看 2.1K关注 0票数 2

will,我有一个包含MainActivity的MainFragment,MainFragment实现了一个RecipeDataFetcher回调接口,该接口将通过RecipeDataFetcher类中的Volley/网络获取数据。MainFragment有一个回收视图,可以显示一些菜谱卡。

-I需要对RecyclerView项执行测试

这是我的主要片段--“公共课程”

代码语言:javascript
运行
复制
MainFragment extends Fragment implements RecipesRecyclerAdapter.OnRecipeItemSelected,
        RecipesDataFetcher.RecipesFetcherDataListener {

    private View v;
    private RecipesDataFetcher recipesDataFetcher;
    private OnFragmentInteractionListener mListener;

private RecyclerView recyclerView;
private RecipesRecyclerAdapter recipesRecyclerAdapter;
private Recipes mRecipes;
private RecyclerView.LayoutManager layoutManager;


private SimpleIdlingResource mIdlingResource;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    v = inflater.inflate(R.layout.fragment_main, container, false);
    mRecipes = new Recipes();
    recyclerView = (RecyclerView) v.findViewById(R.id.rv_recipes);
    if (mTwoPanel) {
        layoutManager = new GridLayoutManager(getActivity(), 2);
    } else {
        layoutManager = new LinearLayoutManager(getActivity());
    }

    recipesRecyclerAdapter = new RecipesRecyclerAdapter(this, mRecipes);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(recipesRecyclerAdapter);
    return v;
}

@VisibleForTesting
@NonNull
public SimpleIdlingResource getIdlingResource() {
    if (mIdlingResource == null) {
        mIdlingResource = new SimpleIdlingResource();
    }
    return mIdlingResource;
}



   @Override
    public void onSaveInstanceState(Bundle outState) {
//        super.onSaveInstanceState(outState);
    }
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

@Override
public void onItemSelected(int itemPosition) {
    mListener.onFragmentInteraction(mRecipes.get(itemPosition), mRecipes.size());
}

@Override
public void onResume() {
    super.onResume();
    if (mRecipes.isEmpty()) {
        getData();
    }
}

@Override
public void onConnectionFailure() {
    if (!checkOnlineState(getActivity())) {
        Logging.shortToast(getActivity(), getString(R.string.internet_error));
    } else {
        Logging.shortToast(getActivity(), getString(R.string.server_error));
    }
}

private void getData() {
    recipesDataFetcher = new RecipesDataFetcher(getActivity(), this);
    recipesDataFetcher.getRecipes(mIdlingResource);
}

@Override
public void onConnectionDone(Recipes recipes) {

    mRecipes.addAll(recipes);
    recipesRecyclerAdapter.notifyDataSetChanged();

    //TODO: Do bulk inset in a background thread and for once
    ContentValues[] contentValues = new ContentValues[recipes.size()];
    for (int i = 0; i < recipes.size(); i++) {
        ContentValues contentValue = new ContentValues();
        Gson gson = new Gson();
        String ingredients = gson.toJson(recipes.get(i).getIngredients());
        String steps = gson.toJson(recipes.get(i).getSteps());
        contentValue.put(COLUMN_RECIPE_INGREDIENTS, ingredients);
        contentValue.put(COLUMN_RECIPE_STEPS, steps);
        contentValue.put(COLUMN_RECIPE_SERVINGS, recipes.get(i).getServings());
        contentValue.put(COLUMN_RECIPE_IMAGE, recipes.get(i).getImage());
        contentValue.put(COLUMN_RECIPE_NAME, recipes.get(i).getName());
        contentValues[i] = contentValue;
    }

    getContext().getContentResolver().bulkInsert(CONTENT_URI, contentValues);

    if(mIdlingResource!=null){
        mIdlingResource.setIdleState(true);
    }

}


public interface OnFragmentInteractionListener {
    void onFragmentInteraction(Recipe recipe, int size);
}`

这是我的dataFetching课程

代码语言:javascript
运行
复制
public class RecipesDataFetcher extends BaseDataFetcher {
    public RecipesDataFetcher(Context context, BaseDataFetcherListener mListener) {
        super(context, mListener);
    }



    public void getRecipes(SimpleIdlingResource simpleIdlingResource) {
            if(simpleIdlingResource!=null){
            simpleIdlingResource.setIdleState(false);}
        String URL = BaseURL;
    Logging.log("getCountries: " + URL);
    JsonArrayRequest jsonObjReq = new JsonArrayRequest(URL, (JSONArray jsonArr) -> {
        Logging.log("getCountries response: " + jsonArr.toString());
        Recipes recipes = new Recipes(jsonArr);
        ((RecipesFetcherDataListener) mListener).onConnectionDone(recipes);
        if(simpleIdlingResource!=null){
            simpleIdlingResource.setIdleState(true);
        }
    }, this.errorListener);
    retryPolicy(jsonObjReq);
    getReQ().add(jsonObjReq);
}

public interface RecipesFetcherDataListener extends BaseDataFetcherListener {
    void onConnectionDone(Recipes recipes);
}

}

A这是我的测试课

代码语言:javascript
运行
复制
 @RunWith(AndroidJUnit4.class)
    public class MyFragmentTest {   

        private SimpleIdlingResource mIdlingResource;

    @Rule
    public FragmentTestRule<MainFragment> mFragmentTestRule = new FragmentTestRule<>(MainFragment.class);

    @Before
    public void registerIdlingResource() {
        // Launch the activity to make the fragment visible
        mFragmentTestRule.launchActivity(null);
         mIdlingResource = mFragmentTestRule.getFragment().getIdlingResource();
        Espresso.registerIdlingResources(mIdlingResource);
    }

    @Test
    public void fragment_can_be_instantiated() {


        // Then to test item in position 0
        onView(withId(R.id.rv_recipes))
                .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
    }

    //  unregister resources
    @After
    public void unregisterIdlingResource() {
        if (mIdlingResource != null) {
            Espresso.unregisterIdlingResources(mIdlingResource);
        }
    }
}

最后,这里是整个代码项目,让我知道我到底做错了什么:D,您的帮助将是非常感谢的。

EN

回答 1

Stack Overflow用户

发布于 2017-06-03 13:40:47

错误的解释

访问您的存储库并运行MyFragmentTest测试类之后

我面临两个错误

  1. com.baking.www.baking.utilities.TestActivity@1d6e5b2必须实现OnFragmentInteractionListener

这是因为在FragmentTestRule类中,您扩展了ActivityTestRule <TestActivity>,其中TestActivity没有实现OnFragmentInteractionListener,因此解决方案是必须扩展MainActivity,后者已经实现了这个接口,因此这个类应该如下所示:

代码语言:javascript
运行
复制
public class FragmentTestRule<F extends Fragment> extends ActivityTestRule<MainActivity> {

private final Class<F> mFragmentClass;
private F mFragment;

public FragmentTestRule(final Class<F> fragmentClass) {
    super(MainActivity.class, true, false);
    mFragmentClass = fragmentClass;
}
.....
  1. 'com.baking.www.baking.IdlingResource.SimpleIdlingResource com.baking.www.baking.fragments.MainFragment.getIdlingResource()‘:尝试在空对象引用上调用虚拟方法java.lang.NullPointerException

这是因为在您的MyFragmentTest中,在任何启动之前调用之前的注释@,这导致您的片段尚未创建,这使得这一行没有意义。

代码语言:javascript
运行
复制
 mIdlingResource = mFragmentTestRule.getFragment().getIdlingResource();

所以在我看来:不要使用片段。活动更容易测试。您可以单独测试每个活动。在大多数情况下,片段并不比活动更有优势。片段只会使实现和测试变得更加困难。

使用volley运行空闲资源的替代解决方案

(a)在MainActivity.java

添加这些行

代码语言:javascript
运行
复制
@Nullable
public SimpleIdlingResource mIdlingResource;

@VisibleForTesting
@NonNull
public SimpleIdlingResource getIdlingResource() {
    if (mIdlingResource == null) {
        mIdlingResource = new SimpleIdlingResource();
    }
    return mIdlingResource;
}

并在您的onCreate中调用此方法getIdlingResource();以从idlingResouce获取实例。

(b)在MainFragment.java中

  • 删除类变量mIdlingResource和它的getMethod
  • 您将发现mIdlingResource的错误
  • 将任何mIdlingResource替换为((MainActivity)getActivity()).mIdlingResource

(c)最后,这是新的MainActivityTest

代码语言:javascript
运行
复制
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

@Rule
public ActivityTestRule<MainActivity> mActivityTestRule =
        new ActivityTestRule<>(MainActivity.class);

private IdlingResource mIdlingResource;


// Registers any resource that needs to be synchronized with Espresso before the test is run.
@Before
public void registerIdlingResource() {
    mIdlingResource = mActivityTestRule.getActivity().getIdlingResource();
    // To prove that the test fails, omit this call:
    Espresso.registerIdlingResources(mIdlingResource);
}

@Test
public void idlingResourceTest() {
    onView(withId(R.id.rv_recipes)).check(matches(isDisplayed()));
    onView(withId(R.id.rv_recipes))
            .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
}

// Remember to unregister resources when not needed to avoid malfunction.
@After
public void unregisterIdlingResource() {
    if (mIdlingResource != null) {
        Espresso.unregisterIdlingResources(mIdlingResource);
    }
}

}

对不起,希望我能帮上忙) :)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44318782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档