4

我一直在試圖弄清楚如何單元測試我的BroadcastReceiver,我看了看StackOverflow和其他網站,但我找不到解決我的問題。單元測試BroadcastReceiver

在我mainActivity我有以下兩個功能:

private void registerNetRcvr(){ 

    if (!isRcvrRegistered) {   
     isRcvrRegistered = true; 
     registerReceiver(receiver, new IntentFilter("android.net.wifi.STATE_CHANGE")); 
     registerReceiver(receiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")); 
    } 
} 

private BroadcastReceiver receiver = new BroadcastReceiver() { 
    public void onReceive(Context context, Intent intent) { 

     NetworkHandler.NetworkInfo netInfo = NetworkHandler.handleBcastReceiver(context); 

     if (netInfo!=null){ 
      handleInfoChange(netInfo); 
     } else { 
      handleInfoChange(null); 
     } 
    } 
}; 

的registerNetRcvr從的onResume函數中調用(和同樣我有在onPause稱爲註銷)。

從上面可以看出,我有一個函數(handleBcastReceiver)被調用來處理onReceive事件,因此有另一個類,然後有從這個函數調用的各種私有函數。

只是稍微複雜一點... onreceive函數被調用,如上所述,'handleBcastReceiver'函數然後將需要'檢索'正確的數據......並且因此將實際調用檢索合適的系統中的數據,如下所示:

private static NetworkInfo getWiFiNetworkInfo(Context context) { 

    ConnectivityManager connManager = (ConnectivityManager) 
      context.getSystemService(Context.CONNECTIVITY_SERVICE); 
    return connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 
} 

我相信,我應該效仿的onReceive的回調行爲,而且我想效仿將從系統調用getWiFiNetworkInfo期間返回。

我的想法是,我應該使用RoboElectric來做到這一點,因爲它可以影響BroadcastReceiver/ConnectivityManager。我也看過Mockito,但我相信RoboElectric是我所需要的,但我相信我很可能是錯的。據我所知,RoboElectric允許我模擬'Android系統',Mockito允許我模擬自己的課程。

目前我只是看不到如何測試BroadcastReceiver。此外,我不清楚我是應該運行模擬器來執行此操作,還是僅僅'運行'我的單元測試,因爲'影子'應該包含我需要的所有內容。最後,如果我想影響BroadcastReceiver,我怎麼通過這個陰影過程使WIFI'啓用'或'禁用'?事實上,我應該模擬一個BroadcastReceiver還是僅僅連接管理器...我真的很困惑!

我到目前爲止所做的是在我的應用程序的測試部分(而不是'androidTest'部分)內創建BroadcastReceiverTest類。我可以對函數進行正常的簡單單元測試,我只是在模仿這個「系統」行爲而堅持。

一如既往,非常感謝任何幫助。

+0

存在問題 - 爲了測試Android應用程序,你需要在特定的,可測試的方式來糾正它。這就是爲什麼現在MVP和技術很受歡迎的原因。 – Divers

回答

2

所以,我想我已經解決了它...... :)如果有更多經驗的人希望給我這方面的反饋,那將是非常感謝。

我覺得我不需要關心'廣播接收器',所以我需要爲連接管理器投影而煩惱,因爲這是'handleBcastReceiver'函數最終讀取的內容。所以,這真的很重要,因爲它是我的功能的「饋送」,它驅動他們的行爲。當onReceive函數被觸發時,它所要做的就是'handleBcastReceiver'函數,然後用結果更新UI,因此這不是我真正需要在這裏測試的。

我創建了以下,它爲我工作。如果我修改我的測試數據,測試將會失敗,所以我相信這是令人滿意的。我希望其他人可能會發現它很有用,正如我所提到的,我很高興收到關於我所做的是或不正確的反饋。

@RunWith(RobolectricTestRunner.class) 
@Config(constants = BuildConfig.class, sdk = 23, manifest = "/src/main/AndroidManifest.xml") 
public class NetworkStateHandlerUnitTest { 

    private static String NETWORK_TYPE_HSDPA = "HSDPA"; 
    private ConnectivityManager connectivityManager; 
    private ShadowConnectivityManager shadowConnectivityManager; 
    private Context context; 

    @Before 
    public void setUp() { 

    } 

    @Test 
    public void handleBroadcastReceiverWIFIConnected() { 

     context = RuntimeEnvironment.application.getApplicationContext(); 
     connectivityManager = getConnectivityManager(); 
     shadowConnectivityManager = Shadows.shadowOf(connectivityManager); 

     //Create shadow Network Info - Connected, WIFI, No Subtype, available, connected 
     NetworkInfo networkInfoShadow = ShadowNetworkInfo.newInstance(NetworkInfo.DetailedState.CONNECTED, ConnectivityManager.TYPE_WIFI, 0, true, true); 
     shadowConnectivityManager.setNetworkInfo(ConnectivityManager.TYPE_WIFI, networkInfoShadow); 

     NetworkHandler.NetworkInfo networkInfoResponse; 

     //Call the function under test 
     networkInfoResponse = NetworkHandler.handleBcastReceiver(context); 

     //Validate the response 
     assertEquals(networkInfoResponse.getNetworkType(), ConnectivityManager.TYPE_WIFI); 
    } 

    private ConnectivityManager getConnectivityManager() { 
     return (ConnectivityManager) RuntimeEnvironment.application.getSystemService(context.CONNECTIVITY_SERVICE); 
    } 
} 

我這樣做,當然已經不僅僅是這一個測試以上,但認爲這將足以幫助別人誰發現自己同樣堅持這一:)

高興地說,我最終成功地測試的BroadcastReceiver監聽器,以及...如果你想知道如何做到這一點...

@Test 
public void handleBrcastRcvrWifiConn() { 

    MainActivity activity = Robolectric.setupActivity(MainActivity.class); 
    TextView tvConnStatus = (TextView) activity.findViewById(R.id.tvConnectionState); 


    context = RuntimeEnvironment.application.getApplicationContext(); 
    connectivityManager = getConnectivityManager(); 
    shadowConnManager = Shadows.shadowOf(connectivityManager); 

    //Create shadow Network Info - Connected, WIFI, No Subtype, available, connected 
    NetworkInfo netInfoShadow = ShadowNetworkInfo.newInstance(NetworkInfo.DetailedState.CONNECTED, 
      ConnectivityManager.TYPE_WIFI, 0, true, true); 
    shadowConnManager.setNetworkInfo(ConnectivityManager.TYPE_WIFI, networkInfoShadow); 


    //Trigger BroadcastReceiver 
    RuntimeEnvironment.application.sendBroadcast(new Intent("android.net.wifi.STATE_CHANGE")); 

    //Validate result by checking value of textView 
    assertEquals("Connected", tvConnectionState.getText()); 

} 
+0

我應該注意到,我學到了很多東西來自這篇文章... http://stackoverflow.com/questions/30625378/shadownetworkinfo-is-always-type-mobile-when-testing-wifi-connectivity-with -robo – greysqrl