<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      我對Stub和Mock的理解

      介紹

      使用測試驅(qū)動開發(fā)大半年了,我還是對Stub和Mock的認識比較模糊,沒有進行系統(tǒng)整理。

      今天查閱了相關(guān)資料,覺得寫得很不錯,所以我試圖在博文中對資料進行整理一下,再加上一些自己的觀點。

      本文是目前我對Stub和Mock的認識,難免有偏差,歡迎大家拍磚。

      分析

      Stub和Mock都是屬于測試替身,對類型細分的話可以分為:

      • Dummy Object
      • Fake Object
      • Test Stub
      • Test Spy
      • Mock Object

      前四項屬于Stub,最后的Mock Object屬于Mock。

      類型分析

      Dummy Object(啞對象)

      測試代碼僅僅是需要使用它來通過編譯,實際上用不到它。如測試A類的run方法,需要在創(chuàng)建A類的實例時需要傳入B類實例,但run方法并沒有用到B類實例。在測試時需要傳入B類的啞對象new NullB()(如“new A(new NullB())”),讓其通過編譯。這里的NullB是一個空類,沒有具體實現(xiàn)。

      Fake Object(假對象)

      假對象相對于啞對象來說,要對耦合的組件有一些簡單的實現(xiàn),實現(xiàn)我們在測試中要用到的方法,指定期望的行為(如返回期望的值)。假對象適用于替換產(chǎn)品代碼中使用的全局對象,或者創(chuàng)建的類。這里注意的是要先對被替換的全局對象或類進行備份,然后在測試完成后進行恢復(fù)。

      示例1(替換全局對象):

      //產(chǎn)品代碼
      function A(){
          this.num = 0;
      }
      A.prototype.run = function(){
         this.num = window.b.getNum();
      };
      
      //測試代碼
      describe("測試A類的run方法", function(){
          var temp = null;
      
          function backUp(){
              window.b = window.b || {};
              temp = YYC.Tool.extendDeep(window.b);
          }
          function restore(){
              window.b = temp;
          }
      
          beforeEach(function(){
              backUp();
          });
          afterEach(function(){
              restore();
          });
      
          it("獲得數(shù)字", function () {
              window.b = {    //假對象
                  getNum: function(){
                      return 1;
                  }
              }
      
              var a = new A();
              a.run();
      
              expect(a.num).toEqual(1);
          });
      });

      示例2(替換類):

      //產(chǎn)品代碼
      function A() {
          this.num = 0;
          this._b = new B();
      }
      A.prototype.run = function () {
          this.num = this._b.getNum();
      };
      
      //測試代碼
      describe("測試A類的run方法", function () {
          var temp = null;
      
          function backUp() {
              window.B = window.B || function () {};
              temp = B;
          }
      
          function restore() {
              window.B = temp;
          }
      
          beforeEach(function () {
              backUp();
          });
          afterEach(function () {
              restore();
          });
      
          it("獲得數(shù)字", function () {
              window.B = function () {
              };
              window.B.prototype.getNum = function () {
                  return 1;
              };
      
              var a = new A();
              a.run();
      
              expect(a.num).toEqual(1);
          });
      });

      Test Stub(測試樁)

      測試樁與假對象有點類似,也要實現(xiàn)與產(chǎn)品代碼耦合的組件,指定期望的行為。這里最大的不同是測試樁需要注入到產(chǎn)品代碼中,從而在測試產(chǎn)品代碼時替換組件,執(zhí)行樁的行為。使用測試樁不需要進行備份和還原。

      示例:

      //產(chǎn)品代碼
      function A(b) {
          this.num = 0;
          this._b = b;
      }
      A.prototype.run = function () {
          this.num = this._b.getNum();
      };
      
      //測試代碼
      describe("測試A類的run方法", function () {
          it("獲得數(shù)字", function () {
              var stub_B = {  //B類的樁
                  getNum: function(){
                      return 1;
                  }
              };
      
              var a = new A(stub_B); //注入樁
              a.run();
      
              expect(a.num).toEqual(1);
          });
      });

      Test Spy(嗅探樁)

      與測試樁類似,但是可以記錄樁使用的記錄,并進行驗證。

      示例:

      可以使用jasmine的spy來舉例。

      //產(chǎn)品代碼
      function A(b) {
          this.num = 0;
          this._b = b;
      }
      A.prototype.run = function () {
          this.num = this._b.getNum();
      };
      
      //測試代碼
      describe("測試A類的run方法", function () {
          it("獲得數(shù)字", function () {
              var stub_b = {
                  getNum: function(){
                      return 1;
                  }
              };
              spyOn(stub_b, "getNum").andCallThrough();   //嗅探樁的getNum方法
      
              var a = new A(stub_b); //注入樁
              a.run();
      
              expect(a.num).toEqual(1);
              expect(stub_b.getNum).toHaveBeenCalled();   //驗證調(diào)用過樁的getNum方法
          });
      });

      Mock Object(模擬對象

      設(shè)定產(chǎn)品代碼中耦合的類的期望的行為,然后驗證期望的行為是否發(fā)生,從而達到測試產(chǎn)品代碼行為的目的。適用于驗證一些void的行為。例如:在某個條件發(fā)生時,要記錄Log。這種情景,用stub就很難驗證,因為對目標物件來說,沒有回傳值,也沒有狀態(tài)變化,就只能通過mock object來驗證目標物件是否正確的與Log介面進行互動。

      示例:

      //產(chǎn)品代碼
      function A(b) {
          this.num = 0;
          this._b = b;
      }
      A.prototype.run = function () {
          this.num = this._b.getNum(2);
      };
      
      //測試代碼(Mock為偽代碼)
      describe("測試A類的run方法", function () {
          it("獲得數(shù)字", function () {
              var mockB = Mock.createMock({
                  getNum: function(){}
              }); //如果B類存在的話,也可以直接傳入B的原型:var mockB = Mock.createMock(B.prototype);
              Mock.expect(mockB.getNum, 2).return(1).times(1);
      
              var a = new A(mockB);
              a.run();
      
              expect(a.num).toEqual(1);
              Mock.verify();  //驗證期望的行為發(fā)生:mockB的getNum傳入的參數(shù)為2;調(diào)用了1次mockB.getNum
          });
      });

      Mock(Mock Object)與Spy(Test Spy)的比較

      相同點

      • 都要注入到產(chǎn)品代碼中。

      不同的

      • Mock是替換整個被Mock的類,這個類可以存在也可以不存在。而Spy是使用一個已經(jīng)存在的類,嗅探其中的部分方法。
      • 從流程中來說,Mock是先設(shè)定被Mock的類的期望行為,然后驗證期望的行為是否發(fā)生。Spy是記錄下樁的方法的使用記錄(如傳入的參數(shù),調(diào)用的次數(shù)等),然后再對記錄進行驗證。

      Mock退化為Stub

      在現(xiàn)實使用中,我們經(jīng)常將mock做不同程度的退化,從而使得mock對象在某些程度上如stub一樣工作。
      使用Mock的示例:
      //產(chǎn)品代碼
      function A(b) {
          this.num = 0;
          this._b = b;
      }
      A.prototype.run = function () {
          this.num = this._b.getNum(2);
      };
      
      //測試代碼(Mock為偽代碼)
      describe("測試A類的run方法", function () {
          it("獲得數(shù)字", function () {
              var mockB = Mock.createMock({
                  getNum: function(){}
              }); //如果B類存在的話,也可以直接傳入B的原型:var mockB = Mock.createMock(B.prototype);
              Mock.expect(mockB.getNum).return(1);    //只指定返回值,沒有期望的參數(shù)或期望調(diào)用的次數(shù)。因此不用verify來驗證了!
      
              var a = new A(mockB);
              a.run();
      
              expect(a.num).toEqual(1);
          });
      });

      也可以用Stub來達到相同的效果:

      //產(chǎn)品代碼
      function A(b) {
          this.num = 0;
          this._b = b;
      }
      A.prototype.run = function () {
          this.num = this._b.getNum();
      };
      
      //測試代碼
      describe("測試A類的run方法", function () {
          it("獲得數(shù)字", function () {
              var stub_B = {
                  getNum: function(){
                      return 1;
                  }
              };
      
              var a = new A(stub_B);
              a.run();
      
              expect(a.num).toEqual(1);
          });
      });

      總結(jié)

      在比較簡單的情況下(如需要啞對象來通過編譯,或是需要測試樁來替換耦合的組件),使用Stub。

      如果需要驗證耦合組件的行為,可以使用Spy或Mock。

      參考資料

      軟件測試- 3 - Mock 和Stub的區(qū)別

      淺談mock和stub

      《xUnit測試模式--測試碼重構(gòu)》

      posted @ 2013-10-25 22:55  楊元超  閱讀(5866)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 少妇人妻综合久久中文字幕| 偷拍美女厕所尿尿嘘嘘小便| 亚洲国产成人精品无码区蜜柚| 久久精品夜色噜噜亚洲aa| 精品三级在线| 好紧好滑好湿好爽免费视频| 亚洲AV国产福利精品在现观看| 看亚洲黄色不在线网占| 国产97人人超碰CAO蜜芽PROM| 久久综合久中文字幕青草| 日本一区二区三区小视频| 含山县| 精品精品国产国产自在线| 亚洲免费成人av一区| 99久久婷婷国产综合精品青草漫画| 国产成人无码免费视频麻豆| 国内自拍小视频在线看| 国产高清精品在线一区二区 | 日本区二区三区不卡视频| 亚洲第一国产综合| 亚洲第一福利网站在线| 九九热免费公开视频在线| 国产一区二区在线影院| 午夜激情福利在线免费看| 男女爽爽无遮挡午夜视频| 国产精品av中文字幕| 成人国产精品中文字幕| 四虎影视国产精品永久在线| 亚洲精品第一页中文字幕| 日韩内射美女人妻一区二区三区| 久久精品一区二区三区av| 国产偷人妻精品一区二区在线 | 亚洲av免费看一区二区| 亚洲精品男男一区二区| 亚洲 制服 丝袜 无码| 国产精自产拍久久久久久蜜| 免费看成人毛片无码视频| 色综合久久精品亚洲国产| 精品无码一区二区三区的天堂| 久久精品久久黄色片看看| 国产精品自拍午夜福利|