will,我有一个包含MainActivity的MainFragment,MainFragment实现了一个RecipeDataFetcher回调接口,该接口将通过RecipeDataFetcher类中的Volley/网络获取数据。MainFragment有一个回收视图,可以显示一些菜谱卡。
-I需要对RecyclerView项执行测试
这是我的主要片段--“公共课程”
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);
}
}
A这是我的测试课
@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,您的帮助将是非常感谢的。
发布于 2017-06-03 13:40:47
对错误的解释
访问您的存储库并运行MyFragmentTest测试类之后
我面临两个错误
这是因为在FragmentTestRule类中,您扩展了ActivityTestRule <TestActivity>,其中TestActivity没有实现OnFragmentInteractionListener,因此解决方案是必须扩展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;
}
.....
这是因为在您的MyFragmentTest中,在任何启动之前调用之前的注释@,这导致您的片段尚未创建,这使得这一行没有意义。
mIdlingResource = mFragmentTestRule.getFragment().getIdlingResource();
所以在我看来:不要使用片段。活动更容易测试。您可以单独测试每个活动。在大多数情况下,片段并不比活动更有优势。片段只会使实现和测试变得更加困难。
使用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中
(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);
}
}
}
对不起,希望我能帮上忙) :)
https://stackoverflow.com/questions/44318782
复制相似问题