Androidµ¥Ôª²âÊÔ½éÉÜ
´¦ÓÚ¸ßËÙµü´ú¿ª·¢ÖеÄAndroidÏîÄ¿ÍùÍùÐèÒª³ýºÚºÐ²âÊÔÍâ¸ü¼Ó¿É¿¿µÄÖÊÁ¿±£ÕÏ£¬ÕâÕýÊǵ¥Ôª²âÊÔµÄÓÃÎäÖ®µØ¡£µ¥Ôª²âÊÔÖÜÆÚÐÔ¶ÔÏîÄ¿½øÐк¯Êý¼¶±ðµÄ²âÊÔ£¬ÔÚÁ¼ºÃµÄ¸²¸ÇÂÊÏ£¬Äܹ»³ÖÐøÎ¬»¤´úÂëÂß¼£¬´Ó¶øÖ§³ÖÏîÄ¿´ÓÈÝÓ¦¶Ô¿ìËٵİ汾¸üС£
µ¥Ôª²âÊÔÊDzÎÓëÏîÄ¿¿ª·¢µÄ¹¤³ÌʦÔÚÏîÄ¿´úÂëÖ®Í⽨Á¢µÄ°×ºÐ²âÊÔ¹¤³Ì£¬ÓÃÓÚÖ´ÐÐÏîÄ¿ÖеÄÄ¿±êº¯Êý²¢ÑéÖ¤Æä״̬»òÕß½á¹û£¬ÆäÖУ¬µ¥ÔªÖ¸µÄÊDzâÊÔµÄ×îСģ¿é£¬Í¨³£Ö¸º¯Êý¡£Èçͼ1ËùʾµÄÂÌÉ«Îļþ¼Ð¼´Êǵ¥Ôª²âÊÔ¹¤³Ì¡£ÕâЩ´úÂëÄܹ»¼ì²âÄ¿±ê´úÂëµÄÕýÈ·ÐÔ£¬´ò°üʱµ¥Ôª²âÊԵĴúÂë²»»á±»±àÒë½øÈëAPKÖС£

ͼ1 µ¥Ôª²âÊÔ¹¤³ÌλÖÃ
ÓëJavaµ¥Ôª²âÊÔÏàͬ£¬Androidµ¥Ôª²âÊÔÒ²ÊÇά»¤´úÂëÂß¼µÄ°×ºÐ¹¤³Ì£¬µ«ÓÉÓÚAndroidÔËÐл·¾³µÄ²»Í¬£¬Androidµ¥Ôª²âÊԵĻ·¾³ÅäÖÃÒÔ¼°ÊµÊ©Á÷³Ì¾ùÓÐËù²»Í¬¡£
Javaµ¥Ôª²âÊÔ
ÔÚ´«Í³Javaµ¥Ôª²âÊÔÖУ¬ÎÒÃÇÐèÒªÕë¶Ôÿ¸öº¯Êý½øÐÐÉè¼Æµ¥Ôª²âÊÔÓÃÀý¡£Èçͼ2±ãÊÇÒ»¸öµäÐ͵ĵ¥Ôª²âÊÔµÄÓÃÀý¡£

ͼ2 µ¥Ôª²âÊÔʾÀý
ÉÏÊöʾÀýÖУ¬Õë¶Ôº¯Êýdosomething(Boolean param)µÄÿ¸ö·ÖÖ§£¬ÎÒÃǶ¼ÐèÒª¹¹ÔìÏàÓ¦µÄ²ÎÊý²¢ÑéÖ¤½á¹û¡£µ¥Ôª²âÊÔµÄÄ¿±êº¯ÊýÖ÷ÒªÓÐÈýÖÖ£º
1.ÓÐÃ÷È·µÄ·µ»ØÖµ£¬ÈçÉÏͼµÄdosomething(Boolean param)£¬×öµ¥Ôª²âÊÔʱ£¬Ö»Ðèµ÷ÓÃÕâ¸öº¯Êý£¬È»ºóÑéÖ¤º¯ÊýµÄ·µ»ØÖµÊÇ·ñ·ûºÏÔ¤ÆÚ½á¹û¡£
2.Õâ¸öº¯ÊýÖ»¸Ä±äÆä¶ÔÏóÄÚ²¿µÄһЩÊôÐÔ»òÕß״̬£¬º¯Êý±¾ÉíûÓзµ»ØÖµ£¬¾ÍÑéÖ¤ËüËù¸Ä±äµÄÊôÐÔºÍ״̬¡£
3.һЩº¯ÊýûÓзµ»ØÖµ£¬Ò²Ã»ÓÐÖ±½Ó¸Ä±äÄĸöÖµµÄ״̬£¬Õâ¾ÍÐèÒªÑéÖ¤ÆäÐÐΪ£¬±ÈÈçµã»÷ʼþ¡£
¼ÈûÓзµ»ØÖµ£¬Ò²Ã»Óиıä״̬£¬ÓÖûÓд¥·¢ÐÐΪµÄº¯ÊýÊDz»¿É²âÊԵģ¬ÔÚÏîÄ¿Öв»Ó¦¸Ã´æÔÚ¡£µ±´æÔÚͬʱ¾ß±¸ÉÏÊö¶àÖÖÌØÐÔʱ£¬±¾ÎĽ¨Òé²ÉÓöà¸öcaseÀ´Õæ¶ÔÿһÖÖÌØÐÔÖðÒ»ÑéÖ¤£¬»òÕß²ÉÓÃÒ»¸öcase£¬ÖðÒ»Ö´ÐÐÄ¿±êº¯Êý²¢ÑéÖ¤ÆäÓ°Ïì¡£
¹¹ÔìÓÃÀýµÄÔÔòÊDzâÊÔÓÃÀýÓ뺯ÊýÒ»¶ÔÒ»£¬ÊµÏÖÌõ¼þ¸²¸ÇÓë·¾¶¸²¸Ç¡£Javaµ¥Ôª²âÊÔÖУ¬Á¼ºÃµÄµ¥Ôª²âÊÔÊÇÐèÒª±£Ö¤ËùÓк¯ÊýÖ´ÐÐÕýÈ·µÄ£¬¼´ËùÓб߽çÌõ¼þ¶¼ÑéÖ¤¹ý£¬Ò»¸öÓÃÀýÖ»²âÒ»¸öº¯Êý£¬±ãÓÚά»¤¡£ÔÚAndroidµ¥Ôª²âÊÔÖУ¬²¢²»ÒªÇó¶ÔËùÓк¯Êý¶¼¸²¸Çµ½£¬ÏñAndroid
SDKÖеĺ¯Êý»Øµ÷Ôò²»ÓòâÊÔ¡£
Androidµ¥Ôª²âÊÔ
ÔÚAndroidÖУ¬µ¥Ôª²âÊԵı¾ÖÊÒÀ¾ÉÊÇÑéÖ¤º¯ÊýµÄ¹¦ÄÜ£¬²âÊÔ¿ò¼ÜÒ²ÊÇJUnit¡£ÔÚJavaÖУ¬±àд´úÂëÃæ¶ÔµÄÖ»ÓÐÀà¡¢¶ÔÏ󡢺¯Êý£¬±àдµ¥Ôª²âÊÔʱ¿ÉÒÔÔÚ²âÊÔ¹¤³ÌÖд´½¨Ò»¸ö¶ÔÏó³öÀ´È»ºóÖ´ÐÐÆäº¯Êý½øÐвâÊÔ£¬¶øÔÚAndroidÖУ¬±àд´úÂëÐèÒªÃæ¶ÔµÄÊÇ×é¼þ¡¢¿Ø¼þ¡¢ÉúÃüÖÜÆÚ¡¢Òì²½ÈÎÎñ¡¢ÏûÏ¢´«µÝµÈ£¬ËäÈ»±¾ÖÊÊÇSDKÖ÷¶¯Ö´ÐÐÁËһЩʵÀýµÄº¯Êý£¬µ«´´½¨Ò»¸öActivity²¢²»ÄÜÈÃËüÖ´Ðе½resumeµÄ״̬£¬Òò´ËÐèÒªJUnitÖ®ÍâµÄ¿ò¼ÜÖ§³Ö¡£
µ±Ç°Ö÷Á÷µÄµ¥Ôª²âÊÔ¿ò¼ÜAndroidTestºÍRobolectric£¬Ç°ÕßÐèÒªÔËÐÐÔÚAndroid»·¾³ÉÏ£¬ºóÕß¿ÉÒÔÖ±½ÓÔËÐÐÔÚJVMÉÏ£¬ËÙ¶ÈÒ²¸ü¿ì£¬¿ÉÒÔÖ±½ÓÓÉJenkinsÖÜÆÚÐÔÖ´ÐУ¬ÎÞÐè×¼±¸Android»·¾³¡£Òò´ËÎÒÃǵĵ¥Ôª²âÊÔ»ùÓÚRobolectric¡£¶ÔÓÚһЩ²âÊÔ¶ÔÏóÒÀÀµ¶È½Ï¸ß¶øÐèÒª½â³ýÒÀÀµµÄ³¡¾°£¬ÎÒÃÇ¿ÉÒÔ½èÖúMock¿ò¼Ü¡£
Androidµ¥Ôª²âÊÔ»·¾³ÅäÖÃ
Robolectric»·¾³ÅäÖÃ
Androidµ¥Ôª²âÊÔÒÀ¾ÉÐèÒªJUnit¿ò¼ÜµÄÖ§³Ö£¬RobolectricÖ»ÊÇÌṩÁËAndroid´úÂëµÄÔËÐл·¾³¡£Èç¹ûʹÓÃRobolectric
3.0£¬ÒÀÀµÅäÖÃÈçÏ£º
testCompile 'junit:junit:4.10' testCompile 'org.robolectric:robolectric:3.0' |
Gradle¶ÔRobolectric 2.4µÄÖ§³Ö²¢²»Ïñ3.0ÕâÑùºÃ£¬µ«Robolectric 2.4ËùÓеIJâÊÔ¿ò¼Ü¾ùÔÚÒ»¸ö°üÀÁíÍâ²Î¿¼×ÊÁÏÒ²±È½Ï·á¸»£¬×÷Õ߸üϰ¹ßʹÓÃ2.4¡£Èç¹ûʹÓÃRobolectric
2.4£¬ÔòÐèÒªÈçÏÂÅäÖãº
classpath 'org.robolectric:robolectric-gradle-plugin:0.14.+'//ÕâÐÐÅäÖÃÔÚbuildscriptµÄdependenciesÖÐ apply plugin: 'robolectric' androidTestCompile 'org.robolectric:robolectric:2.4' |
ÉÏÊöÅäÖÃÖУ¬±¾ÎĽ«testCompileд³ÉandroidTest£¬²¢ÇÒ³£¼ûµÄAndroid¹¤³ÌµÄµ¥Ôª²âÊÔĿ¼Ãû³ÆÓÐtestÒ²ÓÐandroidTest£¬ÕâÁ½ÖÖд·¨²¢Ã»Óй¦ÄÜÉϵIJî±ð£¬Ö»ÊÇAndroidµ¥Ôª²âÊÔTest
Artifact²»Í¬¶øÒÑ¡£Test ArtifactÈçͼ3Ëùʾ£º

ͼ3 Test Artifact
ÔÚGradle²å¼þÖУ¬ÕâÁ½ÖÖArtifactÖ´ÐеÄTask»¹ÊÇÓÐÐ©Çø±ðµÄ£¬µ«ÊDz¢²»Ó°Ïìµ¥Ôª²âÊÔµÄд·¨ÓëЧ¹û¡£ËäÈ»¿ÉÒÔÖ÷¶¯ÅäÖõ¥Ôª²âÊÔµÄÏîĿ·¾¶£¬±¾ÎÄÒÀ¾É½¨Òé²ÉÓÃÓëTest
Artifact¶ÔÓ¦µÄÏîĿ·¾¶ºÍÅäÖÃд·¨¡£
MockÅäÖÃ
Èç¹ûÒª²âÊÔµÄÄ¿±ê¶ÔÏóÒÀÀµ¹ØÏµ½Ï¶à£¬ÐèÒª½â³ýÒÀÀµ¹ØÏµ£¬ÒÔÃâ²âÊÔÓÃÀý¹ýÓÚ¸´ÔÓ£¬ÓÃRobolectricµÄShadowÊǸö°ì·¨£¬µ«ÊÇÍÆ¼ö¸ü¼Ó¼òµ¥µÄMock¿ò¼Ü£¬±ÈÈçMockito£¬¸Ã¿ò¼Ü¿ÉÒÔÄ£Äâ³ö¶ÔÏóÀ´£¬¶øÇÒ±¾ÉíÌṩÁËһЩÑéÖ¤º¯ÊýÖ´ÐеŦÄÜ¡£MockitoÅäÖÃÈçÏ£º
repositories { jcenter() } dependencies { testCompile "org.mockito:mockito-core:1.+" } |
RobolectricʹÓýéÉÜ
Robolectricµ¥Ôª²âÊÔ±àд½á¹¹
µ¥Ôª²âÊÔ´úÂëдÔÚÏîÄ¿µÄtest£¨Ò²¿ÉÄÜÊÇandroidTest£¬¸ÃĿ¼ÔÚÏîÄ¿Öлá³ÊdzÂÌÉ«£©Ä¿Â¼Ï¡£µ¥Ôª²âÊÔÒ²ÊÇÒ»¸ö±ê×¼µÄJava¹¤³Ì£¬ÒÔÀàΪÎļþµ¥Î»±àд£¬Ö´ÐеÄ×îСµ¥Î»ÊǺ¯Êý£¬²âÊÔÓÃÀý£¨ÒÔϼò³Æcase£©ÊÇ´øÓÐ@Test×¢½âµÄº¯Êý£¬µ¥Ôª²âÊÔÀïÃæ´øÓÐcaseµÄÀàÓÉRobolectric¿ò¼ÜÖ´ÐУ¬ÐèҪΪ¸ÃÀàÌí¼Ó×¢½â@RunWith(RobolectricTestRunner.class)¡£»ùÓÚRobolectricµÄ´úÂë½á¹¹ÈçÏ£º
//Ê¡ÂÔÒ»¶Ñimport @RunWith(RobolectricTestRunner.class) public class MainActivityTest { @Before public void setUp() { //Ö´Ðгõʼ»¯µÄ²Ù×÷ } @Test public void testCase() { //Ö´Ðи÷ÖÖ²âÊÔÂß¼ÅÐ¶Ï } } |
ÉÏÊö½á¹¹ÖУ¬´øÓÐ@Before×¢½âµÄº¯ÊýÔÚ¸ÃÀàʵÀý»¯ºó£¬»áÁ¢¼´Ö´ÐУ¬Í¨³£ÓÃÓÚÖ´ÐÐһЩ³õʼ»¯µÄ²Ù×÷£¬±ÈÈç¹¹ÔìÍøÂçÇëÇóºÍ¹¹ÔìActivity¡£´øÓÐ@test×¢½âµÄÊǵ¥Ôª²âÊÔµÄcase£¬ÓÉRobolectricÖ´ÐУ¬ÕâЩcase±¾ÉíÒ²ÊǺ¯Êý£¬¿ÉÒÔÔÚÆäËûº¯ÊýÖе÷Óã¬Òò´Ë£¬caseÒ²ÊÇ¿ÉÒÔ¸´Óõġ£Ã¿¸öcase¶¼ÊǶÀÁ¢µÄ£¬case²»»á»¥ÏàÓ°Ï죬¼´±ãÊÇÏ໥µ÷ÓÃÒ²²»»á´æÔÚ¶àÏ̸߳ÉÈŵÄÎÊÌâ¡£
³£¼ûRobolectricÓ÷¨
RobolectricÖ§³Öµ¥Ôª²âÊÔ·¶Î§´ÓActivityµÄÌø×ª¡¢ActivityչʾView£¨°üÀ¨²Ëµ¥£©ºÍFragmentµ½ViewµÄµã»÷´¥ÃþÒÔ¼°Ê¼þÏìÓ¦£¬Í¬Ê±RobolectricÒ²ÄܲâÊÔToastºÍDialog¡£¶ÔÓÚÐèÒªÍøÂçÇëÇóÊý¾ÝµÄ²âÊÔ£¬Robolectric¿ÉÒÔÄ£ÄâÍøÂçÇëÇóµÄresponse¡£¶ÔÓÚһЩRobolectric²»ÄܲâÊԵĶÔÏ󣬱ÈÈçConcurrentTask£¬¿ÉÒÔͨ¹ý×Ô¶¨ÒåShadowµÄ·½Ê½ÏÖʵ²âÊÔ¡£ÏÂÃæ½«×ÅÖØ½éÉÜRobolectricµÄ³£¼ûÓ÷¨¡£
Robolectric 2.4Ä£ÄâÍøÂçÇëÇó
ÓÉÓÚÉÌÒµAppµÄ¶àÊýActivity½çÃæÊý¾Ý¶¼ÊÇͨ¹ýÍøÂçÇëÇó»ñÈ¡£¬ÒòÎªÍøÂçÇëÇóÊÇ´ó¶àÊýAppÊ×Òª´¦ÀíµÄÄ£¿é£¬²âÊÔÒÀÀµÍøÂçÊý¾ÝµÄActivityʱ£¬¿ÉÒÔÔÚ@Before±ê¼ÇµÄº¯ÊýÖÐ×¼±¸ÍøÂçÊý¾Ý£¬½øÐÐÍøÂçÇëÇóµÄÄ£Äâ¡£×¼±¸ÍøÂçÇëÇóµÄ´úÂëÈçÏ£º
public void prepareHttpResponse(String filePath) throws IOException { String netData = FileUtils.readFileToString(FileUtils. toFile(getClass().getResource(filePath)), HTTP.UTF_8); Robolectric.setDefaultHttpResponse(200, netData); }//´úÂëÊÊÓÃÓÚRobolectric 2.4£¬3.0ÐèҪעÒâÍøÂçÇëÇóµÄ°üµÄλÖà |
ÓÉÓÚRobolectric 2.4²¢²»»á·¢ËÍÍøÂçÇëÇó£¬Òò´ËÐèÒª±¾µØ´´½¨ÍøÂçÇëÇóËù·µ»ØµÄÊý¾Ý£¬ÉÏÊöº¯ÊýµÄfilePath±ãÊDZ¾µØÊý¾ÝµÄÎļþµÄ·¾¶£¬setDefaultHttpResponse()Ôò´´½¨Á˸ÃÇëÇóµÄResponse¡£ÉÏÊöº¯ÊýÖ´Ðк󣬵¥Ôª²âÊÔ¹¤³Ì±ãÓµÓÐÁËÓë±¾µØÊý¾ÝÊý¾Ý¶ÔÓ¦µÄÍøÂçÇëÇó£¬ÔÚÕâ¸öº¯ÊýÖ´ÐкóչʾµÄActivity±ãÊÇÓÐÊý¾ÝµÄActivity¡£
ÔÚRobolectric 3.0»·¾³Ï£¬µ¥Ôª²âÊÔ¿ÉÒÔ·¢ÕæµÄÇëÇ󣬲¢ÇÒÄܹ»ÇëÇóµ½Êý¾Ý£¬±¾ÎÄÒÀ¾É½¨Òé²ÉÓÃmockµÄ°ì·¨¹¹ÔìÍøÂçÇëÇ󣬶ø²»ÒªÒÀÀµÍøÂç»·¾³¡£
Activityչʾ²âÊÔÓëÌø×ª²âÊÔ
´´½¨ÍøÂçÇëÇóºó£¬±ã¿ÉÒÔ²âÊÔActivityÁË¡£²âÊÔ´úÂëÈçÏ£º
@Test public void testSampleActivity(){ SampleActivity sampleActivity£½Robolectric.buildActivity(SampleActivity.class). create().resume().get(); assertNotNull(sampleActivity); assertEquals("ActivityµÄ±êÌâ", sampleActivity.getTitle()); } |
Robolectric.buildActivity()ÓÃÓÚ¹¹ÔìActivity£¬create()º¯ÊýÖ´Ðк󣬸ÃActivity»áÔËÐе½onCreateÖÜÆÚ£¬resume()Ôò¶ÔÓ¦onResumeÖÜÆÚ¡£assertNotNullºÍassertEqualsÊÇJUnitÖеĶÏÑÔ£¬RobolectricÖ»ÌṩÔËÐл·¾³£¬Âß¼Åжϻ¹ÊÇÐèÒªÒÀÀµJUnitÖеĶÏÑÔ¡£
ActivityÌø×ªÊÇAndroid¿ª·¢µÄÖØÒªÂß¼£¬Æä²âÊÔ·½·¨ÈçÏ£º
@Test public void testActivityTurn(ActionBarActivity firstActivity, Class secondActivity) { Intent intent = new Intent(firstActivity.getApplicationContext(), secondActivity); assertEquals(intent, Robolectric.shadowOf(firstActivity).getNextStartedActivity());//3.0µÄAPIÓë2.4²»Í¬ } |
FragmentչʾÓëÇл»
FragmentÊÇActivityµÄÒ»²¿·Ö£¬ÔÚRobolectricÄ£ÄâÖ´ÐÐActivity¹ý³ÌÖУ¬Èç¹û´¥·¢Á˱»²âÊԵĴúÂëÖеÄFragmentÌí¼ÓÂß¼£¬Fragment»á±»Ìí¼Óµ½ActivityÖС£
ÐèҪעÒâFragment³öÏÖµÄʱ»ú£¬Èç¹ûÄ¿±êActivityÖеÄFragmentµÄÌí¼ÓÊÇÖ´ÐÐÔÚonResume½×¶Î£¬ÔÚActivity±»RobolectricÖ´ÐÐresume()½×¶Îǰ£¬¸ÃActivityÖв¢²»»á³öÏÖ¸ÃFragment¡£²ÉÓÃRobolectricÖ÷¶¯Ìí¼ÓFragmentµÄ·½·¨ÈçÏ£º
@Test public void addfragment(Activity activity, int fragmentContent){ FragmentTestUtil.startFragment(activity.getSupportFragmentManager().findFragmentById(fragmentContent)); Fragment fragment = activity.getSupportFragmentManager().findFragmentById(fragmentContent); assertNotNull(fragment); } |
startFragment()º¯ÊýµÄÖ÷Ìå±ãÊdz£ÓõÄÌí¼ÓfragmentµÄ´úÂë¡£Çл»Ò»¸öFragmentÍùÍùÓÉActivityÖеĴúÂëÂß¼Íê³É£¬ÐèÒªActivityµÄÒýÓá£
¿Ø¼þµÄµã»÷ÒÔ¼°¿ÉÊÓÑéÖ¤
@Test
public void testButtonClick(int buttonID){
Button submitButton = (Button) activity.findViewById(buttonID);
assertTrue(submitButton.isEnabled());
submitButton.performClick();
//ÑéÖ¤¿Ø¼þµÄÐÐΪ
} |
¶Ô¿Ø¼þµÄµã»÷ÑéÖ¤Êǵ÷ÓÃperformClick()£¬È»ºó¶ÏÑÔÑéÖ¤ÆäÐÐΪ¡£¶ÔÓÚListViewÕâÀàÉæ¼°µ½AdapterµÄ¿Ø¼þµÄµã»÷ÑéÖ¤£¬Ð´·¨ÈçÏ£º
//listView±»Õ¹Ê¾Ö®ºó
listView.performItemClick(listView.getAdapter().getView(position,
null, null), 0, 0); |
ÓëbuttonµÈ¿Ø¼þÉÔÓв»Í¬¡£
DialogºÍToast²âÊÔ
²âÊÔDialogºÍToastµÄ·½·¨ÈçÏ£º
public void testDialog(){ Dialog dialog = ShadowDialog.getLatestDialog(); assertNotNull(dialog); } public void testToast(String toastContent){ ShadowHandler.idleMainLooper(); assertEquals(toastContent, ShadowToast.getTextOfLatestToast()); } |
ÉÏÊöº¯Êý¾ùÐèÒªÔÚDialog»òToast²úÉúÖ®ºóÖ´ÐУ¬Äܹ»²âÊÔDialogºÍToastÊÇ·ñµ¯³ö¡£
Shadowд·¨½éÉÜ
RobolectricµÄ±¾ÖÊÊÇÔÚJavaÔËÐл·¾³Ï£¬²ÉÓÃShadowµÄ·½Ê½¶ÔAndroidÖеÄ×é¼þ½øÐÐÄ£Äâ²âÊÔ£¬´Ó¶øÊµÏÖAndroidµ¥Ôª²âÊÔ¡£¶ÔÓÚһЩRobolectircÔݲ»Ö§³ÖµÄ×é¼þ£¬¿ÉÒÔ²ÉÓÃ×Ô¶¨ÒåShadowµÄ·½Ê½À©Õ¹RobolectricµÄ¹¦ÄÜ¡£
@Implements(Point.class) public class ShadowPoint { @RealObject private Point realPoint; ... public void __constructor__(int x, int y) { realPoint.x = x; realPoint.y = y; } }//ÑùÀýÀ´Ô´ÓÚRobolectric¹ÙÍø |
ÉÏÊöʵÀýÖУ¬@ImplementsÊÇÉùÃ÷ShadowµÄ¶ÔÏó£¬@RealObjectÊÇ»ñȡһ¸öAndroid
¶ÔÏó£¬constructorÔòÊǸÃShadowµÄ¹¹Ô캯Êý£¬Shadow»¹¿ÉÒÔÐÞ¸ÄһЩº¯ÊýµÄ¹¦ÄÜ£¬Ö»ÐèÒªÔÚÖØÔØ¸Ãº¯ÊýµÄʱºòÌí¼Ó@Implementation£¬ÕâÖÖ·½Ê½¿ÉÒÔÓÐЧÀ©Õ¹RobolectricµÄ¹¦ÄÜ¡£
ShadowÊÇͨ¹ý¶ÔÕæÊµµÄAndroid¶ÔÏó½øÐк¯ÊýÖØÔØ¡¢³õʼ»¯µÈ·½Ê½¶ÔAndroid¶ÔÏó½øÐÐÀ©Õ¹£¬Shadow³öÀ´µÄ¶ÔÏóµÄ¹¦ÄܽӽüAndroid¶ÔÏ󣬿ÉÒÔ¿´³ÉÊǶÔAndroid¶ÔÏóÒ»ÖÖÐÞ¸´¡£×Ô¶¨ÒåµÄShadowÐèÒªÔÚconfigÖÐÉùÃ÷£¬ÉùÃ÷д·¨ÊÇ@Config(shadows=ShadowPoint.class)¡£
Mockд·¨½éÉÜ
¶ÔÓÚһЩÒÀÀµ¹ØÏµ¸´ÔӵIJâÊÔ¶ÔÏ󣬿ÉÒÔ²ÉÓÃMock¿ò¼Ü½â³ýÒÀÀµ£¬³£ÓõÄÓÐMockito¡£ÀýÈçMockÒ»¸öListÀàÐ͵ĶÔÏóʵÀý£¬¿ÉÒÔ²ÉÓÃÈçÏ·½Ê½£º
List list = mock(List.class); //mockµÃµ½Ò»¸ö¶ÔÏó£¬Ò²¿ÉÒÔÓÃ@mock×¢ÈëÒ»¸ö¶ÔÏó |
ËùµÃµ½µÄlist¶ÔÏóʵÀý±ãÊÇListÀàÐ͵ÄʵÀý£¬Èç¹û²»²ÉÓÃmock£¬ListÆäʵֻÊǸö½Ó¿Ú£¬ÎÒÃÇÐèÒª¹¹Ôì»òÕß½èÖúArrayList²ÅÄܽøÐÐʵÀý»¯¡£ÓëShadow²»Í¬£¬Mock¹¹ÔìµÄÊÇÒ»¸öÐéÄâµÄ¶ÔÏó£¬ÓÃÓÚ½âñîÕæÊµ¶ÔÏóËùÐèÒªµÄÒÀÀµ¡£MockµÃµ½µÄ¶ÔÏó½ö½öÊǾ߱¸²âÊÔ¶ÔÏóµÄÀàÐÍ£¬²¢²»ÊÇÕæÊµµÄ¶ÔÏó£¬Ò²¾ÍÊDz¢Ã»ÓÐÖ´ÐйýÕæÊµ¶ÔÏóµÄÂß¼¡£
MockÒ²¾ß±¸Ò»Ð©²¹³äJUnitµÄÑéÖ¤º¯Êý£¬±ÈÈçÉèÖú¯ÊýµÄÖ´Ðнá¹û£¬Ê¾ÀýÈçÏ£º
When(sample.dosomething()).thenReturn(someAction);//when(Ò»¸öº¯ÊýÖ´ÐÐ).thenReturn(Ò»¸ö¿ÉÌæ´úÕæÊµº¯ÊýµÄ½á¹ûµÄ·µ»ØÖµ); //ÉÏÊö´úÂëÊÇÉèÖÃsample.dosomething()µÄ·µ»ØÖµ£¬µ±Ö´ÐÐÁËsample.dosomething()Õâ¸öº¯Êýʱ£¬
¾Í»áµÃµ½someAction£¬´Ó¶ø½â³ýÁ˶ÔÕæÊµµÄsample.dosomething()º¯ÊýµÄÒÀÀµ |
ÉÏÊö´úÂëΪ±»²âº¯Êý¶¨ÒåÒ»¸ö¿ÉÌæ´úÕæÊµº¯ÊýµÄ½á¹ûµÄ·µ»ØÖµ¡£µ±Ê¹ÓÃÕâ¸öº¯Êýºó£¬Õâ¸ö¿ÉÑéÖ¤µÄ½á¹û±ã»á²úÉúÓ°Ï죬´Ó¶ø´úÌæº¯ÊýµÄÕæÊµ½á¹û£¬ÕâÑù±ã½â³ýÁ˶ÔÕæÊµº¯ÊýµÄÒÀÀµ¡£
ͬʱMock¿ò¼ÜÒ²¿ÉÒÔÑéÖ¤º¯ÊýµÄÖ´ÐдÎÊý£¬´úÂëÈçÏ£º
List list = mock(List.class); //MockµÃµ½Ò»¸ö¶ÔÏó list.add(1); //Ö´ÐÐÒ»¸öº¯Êý verify(list).add(1); //ÑéÖ¤Õâ¸öº¯ÊýµÄÖ´ÐÐ verify(list,time(3)).add(1); //ÑéÖ¤Õâ¸öº¯ÊýµÄÖ´ÐдÎÊý |
ÔÚһЩÐèÒª½â³ýÍøÂçÒÀÀµµÄ³¡¾°ÖУ¬¶àʹÓÃMock¡£±ÈÈç¶Ôretrofit¿ò¼ÜµÄÍøÂçÒÀÀµ½â³ýÈçÏ£º
//´úÂë²Î¿¼Á˲ο¼ÎÄÏ×[3] public class MockClient implements Client { @Override public Response execute(Request request) throws IOException { Uri uri = Uri.parse(request.getUrl()); String responseString = ""; if(uri.getPath().equals("/path/of/interest")) { responseString = "·µ»ØµÄjson1";//ÕâÀïÊÇÉèÖ÷µ»ØÖµ } else { responseString = "·µ»ØµÄjson2"; } return new Response(request.getUrl(), 200, "nothing", Collections.EMPTY_LIST,
new TypedByteArray("application/json", responseString.getBytes())); } } //MockClientʹÓ÷½Ê½ÈçÏ£º RestAdapter.Builder builder = new RestAdapter.Builder(); builder.setClient(new MockClient()); |
ÕâÖÖ·½Ê½ÏÂretrofitµÄresponse¿ÉÒÔÓɵ¥Ôª²âÊÔ±àдÕßÉèÖ㬶ø²»À´Ô´ÓÚÍøÂ磬´Ó¶ø½â³ýÁ˶ÔÍøÂç»·¾³µÄÒÀÀµ¡£
ÔÚʵ¼ÊÏîÄ¿ÖÐʹÓÃRobolectric¹¹½¨µ¥Ôª²âÊÔ
µ¥Ôª²âÊԵķ¶Î§
ÔÚAndroidÏîÄ¿ÖУ¬µ¥Ôª²âÊԵĶÔÏóÊÇ×é¼þ״̬¡¢¿Ø¼þÐÐΪ¡¢½çÃæÔªËØºÍ×Ô¶¨Ò庯Êý¡£±¾ÎIJ¢²»ÍƼö¶Ôÿ¸öº¯Êý½øÐÐÒ»¶ÔÒ»µÄ²âÊÔ£¬ÏñonStart()¡¢onDestroy()ÕâЩÖÜÆÚº¯Êý²¢²»ÐèҪȫ²¿¸²¸Çµ½¡£ÉÌÒµÏîÄ¿¶à²ÉÓÃScrumģʽ£¬ÒªÇó¿ìËÙµü´ú£¬ÓÐʱºòδ±ØÓн϶àµÄʱ¼äдµ¥Ôª²âÊÔ£¬²»ÔÙÒªÇóÖð¸öº¯Êýдµ¥Ôª²âÊÔ¡£
±¾Îĵ¥Ôª²âÊÔµÄcase¶àÀ´Ô´ÓÚÒ»¸ö¼ò¶ÌµÄÒµÎñÂß¼£¬µ¥Ôª²âÊÔcaseÐèÒª¶ÔÕâ¶ÎÒµÎñÂß¼½øÐÐÑéÖ¤¡£ÔÚÑéÖ¤µÄ¹ý³ÌÖУ¬¿ª·¢ÈËÔ±¿ÉÒÔÉî¶ÈÁ˽âÒµÎñÁ÷³Ì£¬Í¬Ê±ÐÂÈËÀ´ÁË¿´Ò»ÏÂÏîÄ¿µ¥Ôª²âÊÔ¾ÍÖªµÀÄĸöÂß¼ÅÜÁ˶àÉÙº¯Êý£¬ÐèҪעÒâÄÄЩ±ß½ç¡ª¡ªÊǵ쬵¥Ôª²âÊÔÐèÒªÏñÎĵµÒ»Ñù¾ß±¸ÒµÎñÖ¸µ¼ÄÜÁ¦¡£
ÔÚ´óÐÍÏîÄ¿ÖУ¬Óöµ½ÐèÒª¸Ä¶¯»ùÀàÖдúÂëµÄÐèÇóʱ£¬ÍùÍù²»ÄÜ׼ȷ¿ìËÙµØÖªµÀ¸Ä¶¯ºóµÄÓ°Ï췶Χ£¬½ô¼±Ê±¶à²ÉÓô´½¨×ÓÀา¸Ç¸¸ÀຯÊýµÄ°ì·¨£¬µ«Õâ²»Êdz¤¾ÃÖ®¼Æ£¬ÔÚ×ã¹»¸²¸ÇÂʵĵ¥Ôª²âÊÔÖ§³ÖÏ£¬ÅÜһϵ¥Ôª²âÊÔ¾ÍÖªµÀij¸öº¯Êý¸Ä¶¯ºóµÄÓ°Ï죬¿ÉÒÔ·ÅÐĵØÐ޸ĻùÀà¡£
ÃÀÍŵÄAndroidµ¥Ôª²âÊÔ±àдÁ÷³ÌÈçͼ4Ëùʾ¡£

ͼ4 ÃÀÍÅAndroidµ¥Ôª²âÊÔ±àдÁ÷³Ì
µ¥Ôª²âÊÔ×îÖÕÐèÒªÊä³öÎĵµÊ½µÄµ¥Ôª²âÊÔ´úÂ룬ΪÏßÉÏ´úÂëÌṩÁ¼ºÃµÄ´úÂëÎȶ¨ÐÔ±£Ö¤¡£
µ¥Ôª²âÊÔµÄÁ÷³Ì
ʵ¼ÊÏîÄ¿ÖУ¬µ¥Ôª²âÊÔ¶ÔÏóÓëÒ³ÃæÊÇÒ»¶ÔÒ»µÄ£¬²¢²»½¨Òé¿çÒ³Ãæ£¬ÕâÑùµÄµ¥Ôª²âÊÔźºÏ¶ÈÌ«´ó£¬Î¬»¤À§ÄÑ¡£µ¥Ôª²âÊÔÐèÒªÕÒµ½Ò³ÃæµÄÈë¿Ú£¬·ÖÎöÏîÄ¿Ò³ÃæÖеÄÔªËØ¡¢ÒµÎñÂß¼£¬ÕâÀïµÄÂß¼²»½ö½ö°üÀ¨½çÃæÔªËØµÄչʾÒÔ¼°¿Ø¼þ×é¼þµÄÐÐΪ£¬»¹°üÀ¨´úÂëµÄ´¦ÀíÂß¼¡£È»ºó¿ÉÒÔ´´½¨µ¥Ôª²âÊÔcaseÁÐ±í£¨ÁбíÓÃÓڼͼÏîÄ¿Öе¥Ôª²âÊԵķ¶Î§£¬±ãÓÚµ¥Ôª²âÊԵĹÜÀíÒÔ¼°ÐÂÈËÁ˽âÒµÎñÁ÷³Ì£©£¬ÁбíÖмǼµ¥Ôª²âÊÔ¶ÔÏóµÄÒ³Ãæ£¬¶ÔÏóÖеÄcaseÂß¼ÒÔ¼°Ãû³ÆµÈ¡£¹¤³Ìʦ¿ÉÒÔ¸ù¾ÝÕâ¸öÁÐ±í¿ªÊ¼Ð´µ¥Ôª²âÊÔ´úÂë¡£
µ¥Ôª²âÊÔÊǹ¤³Ìʦ´úÂë¼¶±ðµÄÖÊÁ¿±£Ö¤¹¤³Ì£¬ÉÏÊöÁ÷³Ì²¢²»ÄÜÍêÈ«¸²¸ÇÖØÒªµÄÒµÎñÂß¼ÒÔ¼°±ß½çÌõ¼þ£¬Òò´Ë£¬ÐèҪдÍêºó£¬¿´¸²¸ÇÂÊ£¬ÕÒ³öµ¥Ôª²âÊÔÖÐûÓи²¸Çµ½µÄº¯Êý·ÖÖ§Ìõ¼þµÈ£¬È»ºó¼ÌÐø²¹³äµ¥Ôª²âÊÔcaseÁÐ±í£¬²¢ÔÚµ¥Ôª²âÊÔ¹¤³Ì´úÂëÖв¹ÉÏcase¡£
Ö±µ½¹æ»®µÄÒ³ÃæÖÐËùÓÐÂß¼µÄÖØÒª·ÖÖ§¡¢±ß½çÌõ¼þ¶¼±»¸²¸Ç£¬¸ÃÏîÄ¿µÄµ¥Ôª²âÊÔ½áÊø¡£µ¥Ôª²âÊÔÁ÷³ÌÈçͼ5Ëùʾ¡£

ͼ5 µ¥Ôª²âÊÔÖ´ÐÐÁ÷³Ì
ÉÏÊö·ÖÎöÒ³ÃæÈë¿ÚËùµÃµ½½á¹û±ãÊÇ@Before±ê¼ÇµÄº¯ÊýÖеĴúÂ룬֮ºóµÄÑ»·±ãÊÇËùÓеÄcase£¨@Test±ê¼ÇµÄº¯Êý£©¡£
µ¥Ôª²âÊÔÏîĿʵ¼ù
ΪÁËϵͳµÄ½éÉܵ¥Ôª²âÊÔµÄʵʩ¹ý³Ì£¬±¾ÎÄ´´½¨ÁËÒ»¸öСÐ͵ÄdemoÏîÄ¿×÷Ϊ²âÊÔ¶ÔÏó¡£demoµÄ¹¦ÄÜÊǹ©Óû§·¢²¼Ëù¼ûµÄÐÂÎŵ½·þÎñ¶Ë£¬²¢ä¯ÀÀËùÓÐÒѾ·¢±íµÄÐÂÎÅ£¬ÊǸöµäÐ͵Ä×ÔýÌåÓ¦Ó᣸ÃdemoµÄ¿ª·¢ºÍ²âÊÔÉæ¼°µ½TextView¡¢EditView¡¢ListView¡¢ButtonÒÔ¼°×Ô¶¨ÒåView£¬°üº¬ÁËÍøÂçÇëÇó¡¢¶àÏ̡߳¢Òì²½ÈÎÎñÒÔ¼°½çÃæÌø×ªµÈ¡£Äܹ»Îª¶àÊýÉÌÒµÏîÄ¿Ìṩ²ÎÕÕÑùÀý¡£ÏîÄ¿Ò³ÃæÈçͼ6Ëùʾ¡£

ͼ6 µ¥Ôª²âÊÔcaseÉè¼Æ
Ê×ÏÈÐèÒª·ÖÎöAppµÄÿ¸öÒ³Ãæ£¬Õë¶ÔÒ³ÃæÌáÈ¡³ö¼ò¶ÌµÄÒµÎñÂß¼£¬ÌáÈ¡³öµÄÒµÎñÂß¼Èçͼ6ÂÌɫȦͼËùʾ¡£¸ù¾ÝÕâЩÂß¼À´Éè¼Æµ¥Ôª²âÊÔµÄcase£¨´øÓÐ@Test×¢½âµÄÄǸöº¯Êý£©£¬ÕâÀïµÄÒµÎñÂß¼²»½öÖ¸ÐèÇóÖеÄÒµÎñ£¬»¹°üÀ¨ÆäËûÐèҪά»¤µÄ´úÂëÂß¼¡£ÒµÎñÁ÷³Ì²»ÔÊÐí¿çÒ³Ãæ£¬ÒÔÃâÔö¼Óµ¥Ôª²âÊÔcaseµÄά»¤³É±¾¡£Õë¶ÔdemoÖнçÃæµÄµ¥Ôª²âÊÔcaseÉè¼ÆÈçÏ£º

½ÓÏÂÀ´ÐèÒªÔÚµ¥Ôª²âÊÔ¹¤³ÌÖÐʵÏÖÉÏÊöcase£¬×îС¶ÏÑÔÊýÊÇÒµÎñÂß¼ÉϵÄÅжϣ¬²¢²»ÊÇ´úÂëµÄ±ß½çÌõ¼þ£¬ÕæÊµµÄcaseÐèÒª¿¼ÂÇ´úÂëµÄ±ß½çÌõ¼þ£¬±ÈÈçÊý×éΪ¿ÕµÈÌõ¼þ£¬Òò´Ë£¬×îÖյĶÏÑÔÊýÁ¿»á´óÓÚµÈÓÚ×îС¶ÏÑÔÊý¡£ÔÚÐèÇóÒµÎñÉÏ£¬×îС¶ÏÑÔÊýÒ²ÊǸÃÐèÇóµÄÒµÎñÌõ¼þ¡£
дÍêcaseºóÐèÒªÅÜÒ»±éµ¥Ôª²âÊÔ²¢¼ì²é¸²¸ÇÂʱ¨¸æ£¬µ±¸²¸ÇÂʱ¨¸æÖÐȱÉÙÓÐЩµ¥Ôª²âÊÔcaseÁбíÖÐûÓе«ÊÇʵ¼ÊÂß¼ÖлáÓеÄÂ߼ʱ£¬ÐèÒª¸üе¥Ôª²âÊÔcaseÁÐ±í£¬Ìí¼ÓÒÅ©µÄÂß¼£¬²¢½«¶ÔÓ¦µÄ´úÂë²¹ÉÏ¡£Ö±µ½ËùÓÐÐèҪά»¤µÄÂß¼¶¼±»¸²¸Ç£¬¸ÃÏîÄ¿Öеĵ¥Ôª²âÊÔ²ÅËãÍê³É¡£µ¥Ôª²âÊÔ²¢²»ÊÇQAµÄºÚºÐ²âÊÔ£¬ÐèÒª±£Ö¤¶Ô´úÂëÂß¼µÄ¸²¸Ç¡£
¶Ô±í1·ÖÎö£¬µÚÒ»¸öÒ³ÃæµÄ¡°·¢²¼ÐÂÎÅ¡±µÄcase¿ÉÒÔÖ±½Óµ÷Óá°±àдÐÂÎÅ¡±µÄcase£¬ÒÔÂú×ãÌõ¼þ¡°2.±àдÁËÐÂÎŵÄǰÌáÏ£¬µã»÷·¢²¼°´Å¥¡±£¬ÔÚJUnit¿ò¼ÜÏ£¬case£¨´ø@Test×¢½âµÄÄǸöº¯Êý£©Ò²ÊǸöº¯Êý£¬Ö±½Óµ÷ÓÃÕâ¸öº¯Êý¾Í²»ÊÇcase£¬ºÍcaseÊÇÎ޹صģ¬Á½Õß²¢²»»áÏ໥ӰÏ죬¿ÉÒÔÖ±½Óµ÷ÓÃÒÔ¼õÉÙÖØ¸´´úÂë¡£µÚ¶þ¸öÒ³Ãæ²»Í¬ÓÚµÚÒ»¸ö£¬Ò»½øÈë¾ÍÐèÒªÍøÂçÇëÇ󣬺óÐøÒµÎñ¶¼ÐèÒªÒÀÀµÕâ¸öÍøÂçÇëÇ󣬵¥Ôª²âÊÔ²»Ó¦¸Ã¶Ôijһ¸öÌõ¼þ¹ý¶ÈñîºÏ£¬Òò´Ë£¬ÐèÒªÓÃmock½â³ýñîºÏ£¬Ö±½Ómock³öÍøÂçÇëÇóµÃµ½µÄÊý¾Ý£¬µ¥¶ÀÑéÖ¤Ò³Ãæ¶ÔÊý¾ÝµÄÏìÓ¦¡£
×ܽá
µ¥Ôª²âÊÔ²¢²»ÊÇÒ»¸öÄÜÖ±½Ó²úÉú»Ø±¨µÄ¹¤³Ì£¬ËüµÄÔËÐÐÒÔ¼°¸²¸ÇÂÊÒ²²»ÄÜÖ±½ÓÌáÉý´úÂëÖÊÁ¿£¬µ«Æä´øÀ´µÄ´úÂë¿ØÖÆÁ¦Äܹ»´ó·ù¶È½µµÍ´ó¹æÄ£Ðͬ¿ª·¢µÄ·çÏÕ¡£ÏÖÔÚµÄÉÌÒµApp¿ª·¢¶¼ÊÇ´óÐÍÍŶÓÐ×÷¿ª·¢£¬²»¶Ï»áÓÐÐÂÈ˼ÓÈ룬ÎÞÂÛÐÂÈËÊǸÕÈëÐеÄÓ¦½ìÉú»¹Êǹ¤×÷¶àÄ꣬ÔÚ´úÂë´æÔÚÒ»¶¨ÒµÎññîºÏ¶ÈµÄʱºò£¬Ð޸ĴúÂë¾ÍÓÐÒ»¶¨·çÏÕ£¬¿ÉÄÜ»áÓ°Ïì֮ǰ±È½ÏÒþ±ÎµÄÒµÎñÂß¼£¬»òÕßÊǶªÊ§Ôø¾µÄ²¹¶¡£¬Èç¹ûÓи߸²¸ÇÂʵĵ¥Ôª²âÊÔ¹¤³Ì£¬¾ÍÄܺܿ춨λµ½ÐÂÔö´úÂë¶ÔÏÖÓÐÏîÄ¿µÄÓ°Ï죬ÓëQAÑéÊÕ²»Í¬£¬ÕâÖÖÓ°ÏìÊÇ´úÂë¼¶µÄ¡£
ÔÚ±¾ÎÄËùÉè¼ÆµÄµ¥Ôª²âÊÔÁ÷³ÌÖУ¬µ¥Ôª²âÊÔµÄcaseºÍ¾ßÌåÒ³ÃæµÄ¾ßÌåÒµÎñÁ÷³ÌÒÔ¼°¸ÃÒµÎñµÄ´úÂëÂß¼½ôÃÜÁªÏµ£¬µ¥Ôª²âÊÔÈçͬ¼¼ÊõÎĵµÒ»°ã£¬Äܹ»ÌåÏÖ³öÒ»¸öÒµÎñÂß¼ÔËÐÐÁ˶àÉÙº¯Êý£¬ÐèҪעÒâʲôÑùµÄÌõ¼þ¡£ÕâÊÇÒ»ÖÖÐÂÈËÁ˽âÒµÎñÁ÷³Ì¡¢¶ÔÒµÎñ½øÐдúÂë¼¶±ðÈÚÈëµÄºÃ°ì·¨£¬¿´Ò»ÏÂÒÔǰµÄµ¥Ôª²âÊÔcase£¬¾ÍÄÜÖªµÀÓë¸Ãcase¶ÔÓ¦µÄÄǸöÒ³ÃæÉϵÄÄǸöÒµÎñÂß¼»áÖ´ÐжàÉÙº¯Êý£¬ÒÔ¼°ÕâЩº¯Êý¿ÉÄܳöÏֵĽá¹û¡£
|