gpt4 book ai didi

android - 如何在使用 IdlingResource 获取数据的 fragment 中使用 Espresso 测试 Recycler View

转载 作者:行者123 更新时间:2023-11-29 01:09:23 25 4
gpt4 key购买 nike

会的,我有一个包含 MainFragment 的 MainActivity,MainFragment 实现了一个 RecipeDataFetcher 回调接口(interface),将通过 Volley/network 获取的数据带到 RecipeDataFetcher 类中。MainFragment 有一个 recyclerview,它应该显示几个食谱卡片

-我需要对 RecyclerView 项目执行测试

这是我的主要 fragment `公共(public)类

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 类

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

这是我的测试类

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

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

最佳答案

错误解释

参观完您的存储库并运行 MyFragmentTest 测试类

我遇到了两个错误

  1. java.lang.RuntimeException: com.baking.www.baking.utilities.TestActivity@1d6e5b2 必须实现 OnFragmentInteractionListener

发生这种情况是因为在 FragmentTestRule 类中,您扩展了 ActivityTestRule <TestActivity>,其中 TestActivity 未实现 OnFragmentInteractionListener,因此解决方案是您拥有扩展已经实现此接口(interface)的 MainActivity,因此此类应如下所示:

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. java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“com.baking.www.baking.IdlingResource.SimpleIdlingResource com.baking.www.baking.fragments.MainFragment.getIdlingResource()”

发生这种情况是因为在您的 MyFragmentTest注释 @Before 在任何开始之前被调用,这导致您的 fragment 尚未创建,这使得这一行没有意义

 mIdlingResource = mFragmentTestRule.getFragment().getIdlingResource();

所以在我看来:不要使用 fragment 。 Activity 更容易测试。您可以单独测试每个 Activity 。在大多数情况下,Fragments 与 Activity 相比没有任何优势。 fragment 只会使实现和测试更加困难。

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

(a) 在MainActivity.java

添加这些行

@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 的错误
  • 用 ((MainActivity)getActivity()).mIdlingResource 替换任何 mIdlingResource

(c) 最后这是新的 MainActivityTest

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

}

抱歉,回答太长了希望我能帮上忙 :) :)

关于android - 如何在使用 IdlingResource 获取数据的 fragment 中使用 Espresso 测试 Recycler View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44318782/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com