• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • Android單元測試利器–Robolectric 多線程Demo

    發表于:2016-07-18來源:Cloud Chou.作者:Cloud Chou點擊數: 標簽:單元測試
    首先,我們看一下,被測試的類的源碼,HelloThread的init方法主要功能是啟動一個線程,然后在新線程內部做實際初始化,實際初始化完畢后將初始化狀態標志為成功或者失敗,在本場景

    多線程測試Demo

    本節使用Robolectric+powermock測試多線程的場景。

    首先,我們看一下,被測試的類的源碼,HelloThread的init方法主要功能是啟動一個線程,然后在新線程內部做實際初始化,實際初始化完畢后將初始化狀態標志為成功或者失敗,在本場景里將狀態標志為失敗。在非多線程的場景中,我們進行單元測試時,通常直接對被測試函數的返回值做校驗,而多線程場景中,因為實際功能在另外一條線程里完成,所以對函數的返回值做校驗并沒有實際價值,但是我們可以通過校驗日志來看執行效果。

    被測試的類的源碼如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    
    public class HelloThread {
     
        private InitStatus mInitStatus = InitStatus.INIT;
        private static final String TAG = HelloThread.class.getSimpleName();
     
        public enum InitStatus {
            INIT,
            INITING,
            OK,
            FAILED
        }
     
        private HelloThread() {
        }
     
        private static class HelloThreadHolder {
            private static HelloThread sInstance = new HelloThread();
        }
     
        public static HelloThread getInstance() {
            return HelloThreadHolder.sInstance;
        }
     
        public synchronized void init() {
            if (mInitStatus == InitStatus.INIT) {
                mInitStatus = InitStatus.INITING;
                new Thread() {
                    @Override
                    public void run() {
                        internalInit();
                    }
                }.start();
            }
        }
     
        private void internalInit() {
            System.out.println("========< start init ===>>>");
            try {
                doSomething();
                setInitStatus(InitStatus.OK);
            } catch (Throwable e) {          
                System.out.println("========< init failed ===>>>");
                //初始化失敗后打印日志,這也是我們寫程序時時常見的一種做法,
                //通過日志能幫助程序員更好地定位問題
                SLog.e(TAG, "init failed");
                setInitStatus(InitStatus.FAILED);
            }
            System.out.println("========< finish init ===>>>");
        }
     
        private synchronized void setInitStatus(InitStatus status) {
            mInitStatus = status;
            notifyAll();
        }
     
        public synchronized void waitForInitFinished() throws InterruptedException {
            while (mInitStatus == InitStatus.INITING) {
                wait();
            }
        }
     
        private void doSomething() throws InterruptedException {
            Thread.sleep(3500);
            //假設初始化失敗
            throw new RuntimeException("som exception");
        }
     
    }

    從代碼中可以看到我們在初始化失敗時,會打印error日志,這也讓我們的校驗有了可行性。通過前述章節,我們知道可以對SLog做靜態partial mock, 然后在測試init時,收集執行數據,最后對SLog進行校驗,看其是否打印了指定的error日志即可。 測試代碼如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    @RunWith(RobolectricGradleTestRunner.class)
    @Config(constants = BuildConfig.class, sdk = 21)
    //必須寫如下代碼 讓PowerMock 忽略Robolectric的所有注入
    @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
    //因為我們是針對類做靜態函數的mock,所以必須使用PrepareForTest說明我們要mock的類
    @PrepareForTest({SLog.class})
    public class HelloThreadTest {
     
        //不可缺少的代碼 表明使用Powermock執行單元測試,雖然我們使用的是RoblectricGradleTestRunner來執行單元測試
        //但是添加了如下代碼后RoblectricGradleTestRunner會調用PowerMock的TestRunner去執行單元測試
        @Rule
        public PowerMockRule rule = new PowerMockRule();
     
        @Before
        public void setup() {
            PowerMockito.mockStatic(SLog.class);
        }
     
        @Test
        public void testInit() throws Exception {
            PowerMockito.spy(SLog.class);
            HelloThread.getInstance().init();
            HelloThread.getInstance().waitForInitFinished();
          //因為我們在被測試代碼里調用了SLog.e 日志, 所以verifyStatic  必然失敗
            PowerMockito.verifyStatic(times(0));
            SLog.e(HelloThread.class.getSimpleName(), "init failed");
        }
     
    }

    執行結果如下所示:

    robolectr_thread_demo

    可以看到使用PowerMock 對 多線程程序做校驗是非常方便的

    原文轉自:http://www.cloudchou.com/android/post-966.html?utm_source=tuicool&utm_medium=referral

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>