单元测试 BroadcastReceiver
Unit Testing a BroadcastReceiver
我一直在努力弄清楚如何对我的 BroadcastReceiver 进行单元测试,我查看了 Whosebug 和其他网站,但找不到解决我的问题的方法。
在我的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 事件,因此有另一个 class 然后有各种私有函数,这些函数是从这个调用的功能。
只是为了稍微复杂一点...在调用 onReceive 函数时,如上所述 'handleBcastReceiver' 函数然后需要 'retreive' 正确的数据...因此调用以实际检索适当的系统数据,如下所示:
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 允许我模拟 'the Android system' 而 Mockito 允许我模拟我自己的 classes.
目前我只是看不到如何测试BroadcastReceiver。此外,我不清楚我是否应该 运行 模拟器来执行此操作,或者只是 'run' 我的单元测试,因为 'shadow' 应该包含我需要的一切。最后,如果我要隐藏 BroadcastReceiver,我如何通过这个隐藏过程让 WIFI 成为 'enabled' 或 'disabled'?事实上,我应该模拟 BroadcastReceiver 还是只模拟 ConnectivityManager...我真的很困惑!
到目前为止我所做的是在我的应用程序的测试部分(而不是 'androidTest' 部分)创建一个 BroadcastReceiverTest class。我可以对函数进行正常的简单单元测试,我只是坚持如何模拟这种 'system' 行为。
一如既往,非常感谢您的帮助。
所以,我想我已经解决了...:) 如果有更多经验的人希望就此向我提供反馈,我们将不胜感激。
我觉得我不需要再关心 'broadcast receiver' 所以我需要为隐藏 ConnectivityManager 而烦恼,因为这是 'handleBcastReceiver' 函数最终将从中读取的内容。所以,这才是真正重要的,因为它是 'feed' 到我的函数中,它驱动它们的行为方式。当 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());
}
我一直在努力弄清楚如何对我的 BroadcastReceiver 进行单元测试,我查看了 Whosebug 和其他网站,但找不到解决我的问题的方法。
在我的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 事件,因此有另一个 class 然后有各种私有函数,这些函数是从这个调用的功能。
只是为了稍微复杂一点...在调用 onReceive 函数时,如上所述 'handleBcastReceiver' 函数然后需要 'retreive' 正确的数据...因此调用以实际检索适当的系统数据,如下所示:
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 允许我模拟 'the Android system' 而 Mockito 允许我模拟我自己的 classes.
目前我只是看不到如何测试BroadcastReceiver。此外,我不清楚我是否应该 运行 模拟器来执行此操作,或者只是 'run' 我的单元测试,因为 'shadow' 应该包含我需要的一切。最后,如果我要隐藏 BroadcastReceiver,我如何通过这个隐藏过程让 WIFI 成为 'enabled' 或 'disabled'?事实上,我应该模拟 BroadcastReceiver 还是只模拟 ConnectivityManager...我真的很困惑!
到目前为止我所做的是在我的应用程序的测试部分(而不是 'androidTest' 部分)创建一个 BroadcastReceiverTest class。我可以对函数进行正常的简单单元测试,我只是坚持如何模拟这种 'system' 行为。
一如既往,非常感谢您的帮助。
所以,我想我已经解决了...:) 如果有更多经验的人希望就此向我提供反馈,我们将不胜感激。
我觉得我不需要再关心 'broadcast receiver' 所以我需要为隐藏 ConnectivityManager 而烦恼,因为这是 'handleBcastReceiver' 函数最终将从中读取的内容。所以,这才是真正重要的,因为它是 'feed' 到我的函数中,它驱动它们的行为方式。当 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());
}