【发布时间】:2014-04-25 22:09:34
【问题描述】:
我正在尝试测试我在 Android 中创建的 Fragment。我对代码有完全的控制权,所以我可以在我认为合适的时候改变它。问题是我不确定我缺少什么设计模式才能使其合理。
我正在寻找一种方法来模拟 Android 中不作为参数传递的对象。 This question 建议您可能要模拟的任何内容都应编写为作为参数传递。
这在某些情况下是有意义的,但我不知道如何让它在 Android 上运行,其中一些是不可能的。例如,使用Fragment,您不得不让大部分繁重的工作在回调方法中完成。如何将我的模拟对象放入 Fragment?
例如,在这个ListFragment 中,我需要检索要显示给用户的一系列内容。我正在显示的内容需要动态检索并添加到自定义适配器中。目前看起来如下:
public class MyFragment extends ListFragment {
private List<ListItem> mList;
void setListValues(List<ListItem> values) {
this.mList = values;
}
List<ListItem> getListValues() {
return this.mList;
}
@Override
public void onCreateView(LayoutInflater i, ViewGroup vg, Bundle b) {
// blah blah blah
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
this.setListValues(ListFactory.getListOfDynamicValues());
CustomAdapter adapter = new CustomAdapter(
getActivity(),
R.layout.row_layout,
this.getListValues());
this.setListAdapter(adapter);
}
}
我正在尝试使用 Mockito 和 Robolectric 来做到这一点。
这是我的 robolectric 测试用例的开始:
public class MyFragmentTest {
private MyFragment fragment;
@Before
public void setup() {
ListItem item1 = mock(ListItem.class);
ListItem item2 = mock(ListItem.class);
when(item1.getValue()).thenReturn("known value 1");
when(item2.getValue()).thenReturn("known value 2");
List<ListItem> mockList = new ArrayList<ListItem>();
mockList.add(item1);
mockList.add(item2);
MyFragment real = new MyFragment();
this.fragment = spy(real);
when(this.fragment.getValueList()).thenReturn(mockList);
startFragment();
}
}
这感觉太不对劲了。来自 mockito api 的This section 指出,除非您处理遗留代码,否则您不应该经常进行这样的部分模拟。
此外,我实际上无法使用这种方法模拟 CustomAdapter 类。
做这种事情的正确方法是什么?我在Fragment 课程中的结构是否不正确?我想我也许可以添加一堆包私有设置器,但这仍然感觉不对。
有人可以解释一下吗?我很高兴进行重写,我只想知道一些处理 Fragments 中状态的好模式以及如何使它们可测试。
【问题讨论】:
标签: android unit-testing mockito robolectric