一個演示Junit4實現(xiàn)原理的ut

文|碼術張

本文旨在說明Junit4源代碼的設計思想。
說明方式上,使用的是自己的一個創(chuàng)新的想法:
用一個ut來說明嫡丙。

代碼如下;

package test;

import org.junit.Test;

public class IpTest {

    @Test
    public void should_True() throws Exception{
        MyNotifier notifier = new MyNotifier();
        MyResult result = new MyResult();
        notifier.addListener(result.createListener());
        notifier.addListener(new Detail());
        MyDescription description = MyDescription.createMyDescriptionn("IpTest", "");

        notifier.fireTestRunStarted(description);

            MyDescription descriptionForA = MyDescription.createMyDescriptionn("IpTest", "methodA");

            notifier.fireTestStarted(descriptionForA);
            System.out.println("Hi..., I am method A");
            notifier.fireTestFinished(descriptionForA);

            MyDescription descriptionForB = MyDescription.createMyDescriptionn("IpTest", "methodB");
            notifier.fireTestStarted(descriptionForB);
            System.out.println("Hi..., I am method B");
            notifier.fireTestFinished(descriptionForB);

        notifier.fireTestRunFinished(result);

    }

}

類圖:


類圖

交互圖:


交互圖

在class IpTest中棺榔,有一個should_True方法。
這個方法的實現(xiàn)败砂,即演示了Junit4的實現(xiàn)原理。
MyNotifier龄毡、MyResult吠卷、MyDescription,
對就Junit源碼中類Notifier沦零、Result祭隔、Description。

程序運行時,首先發(fā)布一個事件fireTestRunStarted疾渴;
運行結(jié)束時千贯,發(fā)布一個一個事件fireTestRunFinished。

類的每一個方法運行時搞坝,首先發(fā)布一個事件fireTestStarted搔谴;
類的每一個方法結(jié)束時,會發(fā)現(xiàn)一個事件fireTestFinished桩撮。

Listener收到事件后敦第,會做一些操作。
這些操作的結(jié)果會在程序結(jié)時店量,打印出來:


運行結(jié)果

在Junit源代碼中芜果,每個方法會有一個用職責鏈模式構(gòu)建一個Statement類的對象。
一個方法的執(zhí)行融师,即是依次執(zhí)行這個鏈表上的語句右钾。
這點沒在本文中體現(xiàn)。

本文所用的其他代碼如下:

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MyNotifier {
    private final List<MyRunListener> fListeners =
    Collections.synchronizedList(new ArrayList<MyRunListener>());

    public void addListener(MyRunListener listener) {
        fListeners.add(listener);
    }

    public void fireTestRunStarted(final MyDescription description) throws Exception {
        for (MyRunListener each : fListeners) {
                each.testRunStarted(description);
        }

    }

    public void fireTestRunFinished(final MyResult result) throws Exception{
        for (MyRunListener each : fListeners) {
                each.testRunFinished(result);
        }

    }

    public void fireTestStarted(final MyDescription description) throws Exception{
        for (MyRunListener each : fListeners) {
                each.testStarted(description);
        }       

    }

    public void fireTestFinished(final MyDescription description)   throws Exception{
        for (MyRunListener each : fListeners) {
                each.testFinished(description);
        }   

    }
}

package test;

import java.util.concurrent.atomic.AtomicInteger;

public class MyResult {

    private AtomicInteger fCount = new AtomicInteger();
    private long fRunTime = 0;
    private long fStartTime;

    public int getRunCount() {
        return fCount.get();
    }

    public long getRunTime() {
        return fRunTime;
    }   

    private class Listener extends MyRunListener {
        @Override
        public void testRunStarted(MyDescription description) throws Exception {
            fStartTime = System.currentTimeMillis();
        }

        @Override
        public void testRunFinished(MyResult result) throws Exception {
            long endTime = System.currentTimeMillis();
            fRunTime += endTime - fStartTime;
        }

        @Override
        public void testFinished(MyDescription description) throws Exception {
            fCount.getAndIncrement();
        }

    }   

    public MyRunListener createListener() {
        return new Listener();
    }
}

package test;

import org.junit.runner.notification.Failure;

public class Detail  extends MyRunListener {
    public void testRunStarted(MyDescription description) throws Exception {
        println("==>JUnit4 started with description: \n" + description);
        println();

      }

      public void testRunFinished(MyResult result) throws Exception {
        println("==>JUnit4 finished with result: \n" + describe(result));
      }

      public void testStarted(MyDescription description) throws Exception {
        println("==>Test method started with description: " + description);
      }

      public void testFinished(MyDescription description) throws Exception {
        println("==>Test method finished with description: " + description);
        println();
      }

      public void testFailure(Failure failure) throws Exception {
        println("==>Test method failed with failure: " + failure);
      }

      public void testAssumptionFailure(Failure failure) {
        println("==>Test method assumption failed with failure: " + failure);
      }

      public void testIgnored(MyDescription description) throws Exception {
        println("==>Test method ignored with description: " + description);
        println();
      }

      private String describe(MyResult result) {
        StringBuilder builder = new StringBuilder();
        builder.append("\tRunCount: " + result.getRunCount())
            .append("\n");
        ;
        builder.append("\tRunTime: " + result.getRunTime())
            .append("\n");

        ;
        return builder.toString();
      }

      private void println() {
        System.out.println();
      }

      private void println(String content) {
        System.out.println(content);
      }
}

package test;

public class MyDescription {
    private  String fclassName;
    private  String fMethodName;

    public String getMethodName() {
        return fMethodName;
    }

    public String getClassName() {
        return fclassName;
    }

    @Override
    public String toString() {
        return getDisplayName();
    }

    /**
     * @return a user-understandable label
     */
    public String getDisplayName() {
        return formatDisplayName(fMethodName, fclassName);
    }

    private MyDescription(String className, String methodName) {
        fclassName = className;
        fMethodName = methodName;
    }

    public static MyDescription createMyDescriptionn(String className, String methodName) {
        return new MyDescription( className,  methodName);
    }

    private static String formatDisplayName(String name, String className) {
        return String.format("%s(%s)", name, className);
    }

}

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載旱爆,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者舀射。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市怀伦,隨后出現(xiàn)的幾起案子脆烟,更是在濱河造成了極大的恐慌,老刑警劉巖房待,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浩淘,死亡現(xiàn)場離奇詭異,居然都是意外死亡吴攒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門砂蔽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洼怔,“玉大人,你說我怎么就攤上這事左驾×土ィ” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵诡右,是天一觀的道長安岂。 經(jīng)常有香客問我,道長帆吻,這世上最難降的妖魔是什么域那? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮猜煮,結(jié)果婚禮上次员,老公的妹妹穿的比我還像新娘败许。我一直安慰自己,他們只是感情好淑蔚,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布市殷。 她就那樣靜靜地躺著,像睡著了一般刹衫。 火紅的嫁衣襯著肌膚如雪醋寝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天带迟,我揣著相機與錄音音羞,去河邊找鬼。 笑死邮旷,一個胖子當著我的面吹牛黄选,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播婶肩,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼办陷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了律歼?” 一聲冷哼從身側(cè)響起民镜,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎险毁,沒想到半個月后制圈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡畔况,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年鲸鹦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跷跪。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡馋嗜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吵瞻,到底是詐尸還是另有隱情葛菇,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布橡羞,位于F島的核電站眯停,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏卿泽。R本人自食惡果不足惜莺债,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧九府,春花似錦椎瘟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至儡羔,卻和暖如春宣羊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汰蜘。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工仇冯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人族操。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓苛坚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親色难。 傳聞我的和親對象是個殘疾皇子泼舱,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容