2017-04-14 52 views
0

我有一個應用程序顯示來自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))); 
    } 
} 

我知道這不是編寫測試的正確方法。我希望能夠使用空數據集和非空集來測試兩者,以便if-else是兩個單獨的測試。我認爲我能做到的唯一方法就是模擬數據。

還有別的辦法嗎? 我可以使用Mockito使MainActivity使用模擬數據而無需修改生產代碼嗎?我唯一的選擇是讓它注入真實還是模擬數據提供者來代替我的單身人士?

每次只卸載並重新安裝我的應用程序,因此沒有數據開始,然後繼續進行真正的數據測試,是更好嗎?

+0

你應該嘲笑'DataSingleton'類,以提供測試數據以可控的方式 – njzk2

+0

謝謝,但我不明白的是如何的主要活動,然後使用它? –

+0

您不需要每次都重新安裝應用程序,您可以使用roboguice進行測試並在測試期間注入所需的實現 – mavarazy

回答

0

Android活動重量級且難以測試。因爲我們無法控制構造函數,所以很難交換測試雙打。

要做的第一件事就是確保你依賴於數據源的抽象而不是結核。所以,如果你使用的是單用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; 
     } 
    }; 
} 
相關問題