2016-12-14 52 views
2

我正在按照官方「testing your service」文檔中所述編寫我的NetworkMonitorService的儀器測試。Android:獲取參考開始儀器測試服務

目前我卡住了,因爲我無法弄清楚如何獲取已啓動的服務的引用,以便將mock注入並聲明行爲。

我的代碼:

@RunWith(AndroidJUnit4.class) 
@SmallTest 
public class NetworkMonitorServiceTest { 

    @Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule(); 

    @Test 
    public void serviceStarted_someEventHappenedInOnStartCommand() { 
     try { 
      mServiceTestRule.startService(new Intent(
        InstrumentationRegistry.getTargetContext(), 
        NetworkMonitorService.class)); 
     } catch (TimeoutException e) { 
      throw new RuntimeException("timed out"); 
     } 

     // I need a reference to the started service in order to assert that some event happened 
     // in onStartCommand()... 
    } 
} 

有問題的服務不支持綁定。我認爲,如果我實現了對綁定的支持,然後在測試中使用它,以獲得對該服務可以工作的引用。但是,我不喜歡爲了支持測試用例而編寫產品代碼...

那麼,我該如何測試(儀器測試)一個Service不支持綁定?

+0

用特殊版本「for tests」替換你的應用程序。通過提供定製儀器測試運行器來完成。嘲笑你的依賴它這個「應用程序測試」。查看詳情http://stackoverflow.com/a/41393275/2711056 – MyDogTom

+0

@MyDogTom,我想過這種方法,但我看不到一種簡單的方法來嘲笑服務的依賴這種方式。你能提供一些代碼示例嗎? – Vasiliy

回答

1

用特殊版本「for tests」替換您的應用程序。通過提供定製儀器測試運行器來完成。嘲笑你的依賴它這個「應用程序測試」。 See for details

這裏是一個簡化的例子,說明如何使用「app for test」。假設您想在測試期間模擬網絡層(例如Api)。

public class App extends Application { 
    public Api getApi() { 
     return realApi; 
    } 
} 

public class MySerice extends Service { 
    private Api api; 
    @Override public void onCreate() { 
     super.onCreate(); 
     api = ((App) getApplication()).getApi(); 
    } 
} 

public class TestApp extends App { 
    private Api mockApi; 

    @Override public Api getApi() { 
     return mockApi; 
    } 

    public void setMockApi(Api api) { 
     mockApi = api; 
    } 
} 

public class MyTest { 
    @Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule(); 

    @Before public setUp() { 
     myMockApi = ... // init mock Api 
     ((TestApp)InstrumentationRegistry.getTargetContext()).setMockApi(myMockApi); 
    } 

    @Test public test() { 
     //start service 
     //use mockApi for assertions 
    } 
} 

在示例依賴注入通過應用程序的方法getApi完成。但是你可以用同樣的方式使用Dagger或其他任何方法。

+0

謝謝,但我已經嘗試過這種方法。這裏的問題是,它不允許爲每個測試注入模擬 - 您將爲將要運行的所有測試指定模擬。對於小型應用程序來說,這可能會正常工作,但在大型應用程序中(我的Dagger 2對象圖包含〜10個模塊中的數百個對象,這些對象被〜5個組件使用)您想要做的是爲每個測試注入模擬。我找不到用這種方法做到這一點的簡單方法。你是否? – Vasiliy

+0

@Vasiliy我只使用這種方法進行集成測試,只嘲笑最大/最慢的依賴(後端,在應用層)。對於單元測試,我將邏輯提取到單獨的pojo(或幾乎pojo)類中,併爲此類編寫測試。在你的情況下,你的服務可以使用某種包含所有邏輯的幫助器。用一堆單元測試覆蓋這個幫助者。編寫幾個集成測試只是爲了看到所有東西都可以一起工作。此時您無需覆蓋所有情況。 – MyDogTom

+0

是的,這正是我現在所處的位置 - 我對「助手」和「經理」進行了單元測試,但是我希望對整個服務進行集成測試。然而,我沒有看到一種方式來編寫集成測試,沒有嘲諷某些特定服務的依賴關係(至少我需要模擬Android的ConnectivityManager,EventBus,ServerPingManager)。但是我不想嘲笑所有測試的這些依賴關係 - 還有一些測試應該仍然使用非模擬依賴關係。無論如何,謝謝你的好主意。 +1 – Vasiliy