我正在尝试编写Espresso单元测试,该测试依赖于使TCP/IP网络连接到外部应用程序以便成功通过的组件.
测试失败的原因是TCP/IP网络花费的时间比Espresso允许的时间长......
因此,我们需要有TCP/IP代码类TCPConnectionTask实现IdlingResource:
但是,我得到了这个例外:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.(Handler.java:200)
at android.os.Handler.(Handler.java:114)
at android.app.Activity.(Activity.java:786)
at com.sample.QuicksetSampleActivity.(QuicksetSampleActivity.java:82)
at com.unitTests.QuicksetSampleActivityTest.(QuicksetSampleActivityTest.java:52)
我附上TCPConnectionTask
并打电话Looper.prepare()
和尝试过Looper.prepareMainLooper()
,没有成功,见下文(TCPConnectionTask)
:
/** * Async task to connect to create TCPIPDataComm and connect to external IRB. * */ public class TCPConnectionTask extends AsyncTaskimplements IdlingResource { String ip_user = null; int port_user; private ResourceCallback callback; private boolean flag = false; protected Void doInBackground(String... args) { try { Handler handler = new Handler(Looper.getMainLooper()); handler.post( new Runnable() { @Override public void run() { Looper.prepare(); //Looper.prepareMainLooper(); flag = true; TCPIPDataComm tcp = new TCPIPDataComm(ip_user, port_user); if(tcp != null){ tcp.open(); _TCPDataComm = tcp; // we can enable the DataComm interface for simulation in UI app int resultCode = 0; try { resultCode = QuicksetSampleApplication.getSetup().setDataCommInfo( getAuthKey(), _TCPDataComm.getHostName(), _TCPDataComm.getPortNumber()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { //task completed flag = false; } Log.d(QuicksetSampleActivity.LOGTAG, "Setting DataComm Result = " + resultCode + " - " + ResultCode .getString(resultCode)); } } } ); } catch (Exception e) { e.printStackTrace(); } return null; } public void setInfo(String ipValue, int portNumber) { ip_user = ipValue; port_user = portNumber; } @Override public String getName() { return this.getClass().getName().toString(); } @Override public boolean isIdleNow() { if (flag && callback != null) { callback.onTransitionToIdle(); } return flag; } @Override public void registerIdleTransitionCallback(ResourceCallback callback) { this.callback = callback; } }
以下是单元测试类的相关片段QuicksetSampleActivityTest
:
@RunWith(AndroidJUnit4.class) public class QuicksetSampleActivityTest extends ActivityInstrumentationTestCase2{ private QuicksetSampleActivity newQuicksetSampleActivity = null; private final String ip = "192.168.43.139"; private final int port = 9999; private final int timeOutTime = 1000; //This is the idling resource that takes time to complete due to network latency... private QuicksetSampleActivity.TCPConnectionTask taskIdlingResource = null; //const public QuicksetSampleActivityTest() { super(QuicksetSampleActivity.class); //instantiation of idling resource that is used for TCP connection taskIdlingResource = new QuicksetSampleActivity().new TCPConnectionTask(); } @Before public void setUp() throws Exception { super.setUp(); injectInstrumentation(InstrumentationRegistry.getInstrumentation()); //open activity newQuicksetSampleActivity = getActivity(); // Make sure Espresso does not time out IdlingPolicies.setMasterPolicyTimeout(timeOutTime * 10, TimeUnit.MILLISECONDS); IdlingPolicies.setIdlingResourceTimeout(timeOutTime * 10, TimeUnit.MILLISECONDS); //register idling resource Espresso.registerIdlingResources(taskIdlingResource); } @After public void unregisterIntentServiceIdlingResource() { //unregister idling resource Espresso.unregisterIdlingResources(taskIdlingResource); } //The EditText GUI with the port & Ip was noe found using espresso, we need to set teh ip & port programmatically public void setIpandPortToPcBridge() { // Use TCPCommunicatuonTask interface taskIdlingResource.setInfo(ip, port); taskIdlingResource.execute(); } //after TCP connection is made and/or tested @Test public void testActionBarMenuItemsIrDevicesAfterTCPConnectionFunctions() { //we were not able to find the IP & Port fields so set them programmatically setIpandPortToPcBridge(); //open action bar menu Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext()); //test IR Devices/Functions menu item Espresso.onData(Matchers.allOf(Matchers.instanceOf(MenuItem.class), MatcherUtility.menuItemWithTitle("IR Devices/Functions"))).perform(ViewActions.click()); //add new device will connect the app Espresso.onView(ViewMatchers.withId(R.id.btAdd)).perform(ViewActions.click()); //DeviceFunctionsActivity is rendered Espresso.onView(ViewMatchers.withText("IR Devices")).check(ViewAssertions.matches(ViewMatchers.withText("IR Devices"))); //find the 3 required buttons for this UI //test START learning //Espresso.onView(ViewMatchers.withText("Start")).check(ViewAssertions.matches(ViewMatchers.withText("Start"))); //click //test CANCEL learning //test TEST Learned IR //Espresso.onView(ViewMatchers.withText("Test Learned IR")).check(ViewAssertions.matches(ViewMatchers.withText("Test Learned IR"))); //click //test Delete Learn Code // Espresso.onView(ViewMatchers.withText("Delete Learn Code")).check(ViewAssertions.matches(ViewMatchers.withText("Delete Learn Code"))); //click //go back //ViewActions.pressBack(); } } }
如何解决此异常,并IdlingResource
成功运行Espresso ?
尝试
getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { // Your testActionBarMenuItemsIrDevicesAfterTCPConnectionFunctions() test body } });