我有一个应用程序,它显示来自Web API的数据(帖子)。
我目前正在测试主要活动如下
@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class);
@Test
public void testDataLoad() {
int postsTotal = DataSingleton.getInstance().getPostsCount();
ViewInteraction empty = onView(withId(R.id.empty_view));
ViewInteraction recycler = onView(withId(R.id.recycler_view));
if (postsTotal == 0) {
empty.check(matches(isDisplayed()));
recycler.check(matches(not(isDisplayed())));
} else {
empty.check(matches(not(isDisplayed())));
recycler.check(matches(isDisplayed()));
recycler.check(new RecyclerViewItemCountAssertion(greaterThan(postsTotal)));
}
}
我知道这不是编写测试的正确方法。我希望能够使用空数据集和非空集测试两者,以便if-else是两个单独的测试。我认为我能实现的唯一方法是模拟数据。
还有其他方法吗? 我可以使用Mockito使MainActivity使用模拟数据而无需修改生产代码吗?是我唯一的选择,让它注入真实或模拟的数据提供者来代替我的单身人士吗?
每次只卸载并重新安装我的应用程序是否更好,因此没有数据可以开始,然后继续进行实际数据测试?
答案 0 :(得分:0)
Android Activity很重,很难测试。因为我们无法控制构造函数,所以很难交换测试双精度。
要做的第一件事是确保依赖于数据源的抽象而不是结果。因此,如果您使用带有getPostsCount()
方法的单例,则提取接口:
interface DataSourceAbstraction {
int getPostsCount();
}
创建一个实现接口的包装类:
class ConcreteDataSource implements DataSourceAbstraction {
@Override
int getPostsCount() {
return DataSingleton.getInstance().getPostsCount();
}
}
并使活动依赖于而不是具体的DataSingleton
DataSourceAbstraction dataSourceAbstraction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super(savedInstanceState);
injectMembers();
}
@VisibleForTesting
void injectMembers() {
dataSourceAbstraction = new ConcreteDataSource();
}
现在,您可以通过子类化和覆盖具有宽松可见性的injectMembers
来交换测试双精度。在企业开发中这样做是个坏主意,但是在Android活动中没有控制类的构造函数的选项较少。
您现在可以写:
DataSourceAbstraction dataSource;
//system under test
MainActivity mainActivity
@Before
public void setUp() {
mockDataSource = Mockito.mock(DataSourceAbstraction.class);
mainActivity = new MainActivity() {
@Override
void injectMembers() {
dataSourceAbstraction = mockDataSource;
}
};
}