单元测试基于BroadcastReceiver的服务获取wifi的SSID列表并返回Rx.Observable

时间:2016-12-19 13:36:23

标签: android unit-testing rx-java android-testing rx-android

我正在尝试测试我的ServiceHelper类,它提供了一个Wifi的SSID列表,以便在我的视图中显示。 所以我使用RxJava + RxAndroid提供了一个observable。正如你所看到的,我选择了Observable.create()来创建本机我的observable(Arraylist of Items)女巫取决于BroadcastReciever内部类。 我需要测试这个方法的单位。我不知道如何测试或模拟这种依赖于传感器的服务。

public class WifiPhoneServiceHelper {

private Context context;
private ArrayList<String> ssidList = new ArrayList<>();
private List<ScanResult> scanResultList;
private WifiManager wifiManager;

public WifiPhoneServiceHelper(Context context) {
    this.context = context;
}

public Observable<ArrayList<String>> getObservableSsidWifiList() {
    return Observable.create(new Observable.OnSubscribe<ArrayList<String>>() {

        @Override
        public void call(final Subscriber<? super ArrayList<String>> subscriber) {
            wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

            final BroadcastReceiver receiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                        scanResultList = wifiManager.getScanResults();
                        for (int i = 0; i < scanResultList.size(); i++) {
                            String ssidDetected = scanResultList.get(i).SSID;
                            ssidList.add(ssidDetected);
                        }
                        subscriber.onNext(ssidList);
                    }
                }
            };

            context.registerReceiver(receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

            if (!wifiManager.isWifiEnabled()) {
                wifiManager.setWifiEnabled(true);
            }
            wifiManager.startScan();

            subscriber.add(new MainThreadSubscription() {
                @Override
                protected void onUnsubscribe() {
                    context.unregisterReceiver(receiver);
                    Timber.d("unregisterReceiver BroadcastReceiver SCAN_RESULTS_AVAILABLE_ACTION");
                    if (!subscriber.isUnsubscribed()) {
                        subscriber.unsubscribe();
                    }
                }
            });
        }
    });
}

2 个答案:

答案 0 :(得分:1)

为了对您的代码进行单元测试,您需要将所有功能描述到单独的界面中,然后为Android实现它并为单元测试创​​建模拟实现(Mockito)。

答案 1 :(得分:1)

Alex有效地建议您在代码和Wi-Fi系统之间创建一个界面,而生产代码则由Android的WifiManager实现,但在测试中,由您自己的测试工具实现。

你当然可以这样做,但另一种选择是Robolectric。这是一个Android单元测试框架,可用于模拟Android系统的大部分内容,而无需像Mockito那样做足够的基础工作。具体来说,它可以模拟Wi-Fi系统,因此您可以让它假装给定的网络存在或不存在。这样做的好处是你可以在很大程度上使用代码保留你的Wi-Fi,而无需进行大量的重构测试,但你仍然不需要真正的设备而且它不依赖于现实世界&# 39;网络环境。

特别要查找基于ShadowWifiManager的示例。另一半难题是制作事件广播来刺激你的代码,但这也应该是可行的。

完全描述Robolectric测试环境的建立超出了本答案的范围,但希望能为您提供一些开始研究的东西。