Android 如何使我的活动使用测试数据?

Android 如何使我的活动使用测试数据?,android,testing,mockito,android-espresso,Android,Testing,Mockito,Android Espresso,我有一个应用程序,它显示来自web API的数据(帖子) 后台服务在未知时间同步此数据并保存它 访问我的主要活动时,它会加载此数据并将其显示在RecyclerView中 加载是通过单例类处理的 我目前测试的主要活动如下 @Rule public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class); @Test public void tes

我有一个应用程序,它显示来自web API的数据(帖子)

  • 后台服务在未知时间同步此数据并保存它
  • 访问我的主要活动时,它会加载此数据并将其显示在RecyclerView中
  • 加载是通过单例类处理的
我目前测试的主要活动如下

@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)));
    }
}
@规则
public ActivityTestRule mActivityRule=新的ActivityTestRule(MainActivity.class);
@试验
public void testDataLoad(){
int postsTotal=DataSingleton.getInstance().getPostScont();
ViewInteraction empty=onView(带id(R.id.empty_视图));
ViewInteraction recycler=onView(带id(R.id.recycler_视图));
if(postsTotal==0){
空。检查(匹配项(isDisplayed());
回收器。检查(匹配项(不是(isDisplayed())));
}否则{
空。检查(匹配项(不是(isDisplayed()));
检查(匹配项(isDisplayed());
检查(新的RecycleServiceItemCountAssertion(大于(postsTotal)));
}
}
我知道这不是编写测试的正确方法。我希望能够使用一个空数据集和一个非空数据集来测试这两个测试,以便if-else是两个独立的测试。我认为实现这一目标的唯一方法是模拟数据

还有别的办法吗? 我可以使用Mockito使MainActivity在不修改生产代码的情况下使用模拟数据吗?我唯一的选择是让它注入真实或模拟的数据提供者来代替我的单例吗


每次卸载并重新安装我的应用程序,这样就没有数据可供开始,然后继续进行真实数据测试是否更好?

Android活动是重量级的,很难测试。因为我们无法控制构造函数,所以很难在测试中交换双精度

首先要做的是确保您依赖于数据源的抽象,而不是具体化。因此,如果使用带有
getPostScont()
方法的单例,则提取一个接口:

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

您应该模拟
DataSingleton
类,以受控的方式提供测试数据谢谢,但我不明白的是主活动随后如何使用它?您不需要每次都重新安装应用程序,您可以使用roboguice进行测试,并在测试期间注入所需的实现