亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

模擬對象和存根

2019-11-14 14:25:34
字體:
來源:轉載
供稿:網友

 在單元測試中存根和模擬對象處于一個非常重要的地位以下我就來說說我對兩者的理解。

1:什么是交互測試

工作單元最終的三種結果類型:

  • 基于值的測試:驗證函數返回值
  • 基于狀態的測試:驗證通過被測試函數之后狀態的變化
  • 交互測試:驗證一個對象如何向另一個對象(一般是第三方服務)發送消息(調用方法)

重點說一下交互測試:如果一個特定的工作單元最終的結果就是調用另一個對象那么就要進行交互測試。簡單來說就是你無法判斷你是否調用了這個方法,因為他的返回值是void,那么你只能通過其他方式來判斷你確實調用了這個方法。這整個過程就就是交互測試。

2:模擬對象

什么是模擬對象:模擬對象也是偽對象,它可以驗證被測試對象是否按照預期的方式調用了這個偽對象,因此來判斷單元測試的成功或者失敗。

舉一個例子:小明由于作業沒有做完,老師就讓小明放學之后晚回家一個小時來寫作業,那么今天老師有事就提前回家了,就讓班長小亮來查看小明是否留下來一個小時在寫作業。此時小亮就是我們說的偽對象,他就檢測了小明是否晚回家一個小時。

3:模擬對象和存根的區別

1:存根上一篇已經說了現在我們看一下圖

很明顯我們斷言的對象是被測試類下面是模擬對象

這個是對模擬對象的斷言。

其實他們區別很小,他們的根本區別就是存根不會導致測試的失敗而模擬對象卻可以(存根由于斷言是對被測試類所以不會導致測試失敗,而模擬對象恰恰相反)

模擬對象就是來檢測你的測試是否會失敗。下面看例子

4:模擬對象和存根的使用

現在我引用一個外部的LogService專門記錄錯誤日志,但是這個日志是void類型無法返回這個時候模擬對象就派上用場。我們先定義個一個日志服務接口

public interface ILogService    {        void ErrorLog(string message);    }

被測試代碼

PRivate readonly ILogService _logService;        public UserManager(ILogService logService)//模擬對象注入        {            this._logService = logService;        }        public void RecordLog(string userName)        {            if (userName.Length<=4)//名稱長度小于4就記錄日志異常            {                _logService.ErrorLog(userName);            }        }

模擬對象

public class FakeLogService:ILogService    {        public string Message;//記錄錯誤信息        public void ErrorLog(string message)        {            this.Message = message;        }    }

測試代碼

[Category("模擬對象")]        [Test]        public void RecordLog_UserNameTooShort_CallLogService()        {            var mockService=new FakeLogService();            var userManager=new UserManager(mockService);//注入模擬對象            userManager.RecordLog("lp");//記錄錯誤日志            Assert.AreEqual("lp", mockService.Message);//如果錯誤信息和模擬對象的相同說明我已經調用了這個方法并正確的傳遞了值        }

我們看一下測試效果:

我們發現測試過去了說明我們已經的方法正確的調用和傳遞值給日志服務。這個測試保證的是我們調用日志方法沒有錯誤。

存根和模擬對象的同時使用

有時候一個方法體有2個未能返回值的方法,那么這個時候你可能就要確定一下哪個是存根哪個是模擬對象了。

比喻現在我們又加入一個需求,如果出現錯誤日志異常就要給系統管理員發一份郵件,這個時候我們就發現自己有2個沒有返回值的函數,不建議寫2個模擬對象,那樣就會造成混亂你不知道到底是哪個方法出現錯誤(因為斷言是針對于模擬對象的)

先定義一個郵件發送接口

public interface IEmailService    {        void SendEmail(string user, string subject, string content);    }

模擬對象實現這個接口

public class FackEmailService : IEmailService    {        public string User { get; set; }        public string Subject { get; set; }        public string Content { get; set; }        public void SendEmail(string user, string subject, string content)        {            this.User = user;            this.Subject = subject;            this.Content = content;        }    }

我們在看看被測試的代碼

public class UserManager    {        public void RecordLog(string userName)        {            try            {                if (userName.Length <= 4) //名稱長度小于4就記錄日志異常                {                    LogManager().ErrorLog(userName);                }            }            catch (Exception ex)            {                EmailService().SendEmail("lp", "subject", ex.Message);            }        }        protected virtual ILogService LogManager()//底層可替換        {            return new LogService();        }
protectedvirtual IEmailService EmailService()
{
returnnew EmailService();
} }

創建新類繼承被測試類來完成底層替換

    public class TestUserManager : UserManager    {        private readonly ILogService _logService;        private readonly IEmailService _emailService;        public TestUserManager(ILogService logService, IEmailService emailService)        {            _logService = logService;            _emailService = emailService;        }        public override IEmailService EmailService()        {            return _emailService;        }        public override ILogService LogManager()        {            return _logService;        }    }

測試代碼

       [Test]        public void RecordLog_EmailServiceThrows_SendsEmail()        {            var stubLogService = new FakeLogService() {Exception = new Exception("fack exception")};//日志的模擬對象拋出異常(這個是存根)            var mokeEmailService = new FackEmailService();            var testUser = new TestUserManager(stubLogService, mokeEmailService);//注入存根和模擬對象            testUser.RecordLog("lp");            StringAssert.Contains("lp",mokeEmailService.User);            StringAssert.Contains("subject",mokeEmailService.Subject);            StringAssert.Contains("fack exception",mokeEmailService.Content);        }

我們看看測試結果

你也可以把三個屬性封裝成一個實體對實體進行斷言。

 5:偽對象鏈

什么是對象鏈:就是一個對象的屬性是另一個對象然后這個對象的屬性又是一個對象。比喻我們經??吹降腃onfigurationManager.ConnectionStrings[0].ConnectionString這個就是一個對象鏈。

如果我們在測試的時候就發現需要偽造2個對象如果很多的話就可能偽造的更多,所以我們在重構代碼的時候就要考慮可測的代碼如下這樣就測試就可以直接替代

    protected virtual string GetConnectionString()        {            return ConfigurationManager.ConnectionStrings[0].ConnectionString;        }

6:手工模擬對象和存根的存在的問題

  • 編寫模擬對象和存根耗時間
  • 如果接口有很多方法、屬性、事件編寫的時候會特別困難
  • 如果驗證調用者向另一個方法調用傳遞的所有參數都是正確的時候就需要多次進行斷言。
  • 有些模擬對象就是為特定的方法編寫復用性比較差

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91视频九色网站| 中文字幕亚洲综合久久| 亚洲天堂影视av| 色婷婷久久一区二区| 欧美日韩国产精品专区| 91美女片黄在线观看游戏| 亚洲国产精品久久精品怡红院| 伊人一区二区三区久久精品| 亚洲人成亚洲人成在线观看| 欧美一区二区影院| 国产精品久久久久一区二区| 中文字幕无线精品亚洲乱码一区| 日本一本a高清免费不卡| 亚洲精品国偷自产在线99热| 91影院在线免费观看视频| 欧美亚洲成人xxx| 91久久久亚洲精品| 国产中文字幕日韩| 国产精品日韩在线一区| 日本aⅴ大伊香蕉精品视频| 亚洲精品av在线播放| 精品国产一区二区三区在线观看| 精品亚洲夜色av98在线观看| 国产成人一区二区三区电影| 奇米成人av国产一区二区三区| 久久精品视频99| 中文字幕国产精品久久| 久久精品成人动漫| 亚洲欧美制服综合另类| 最新日韩中文字幕| 国产亚洲美女久久| 国产亚洲精品美女| 久久精品99无色码中文字幕| 亚洲精品小视频| 亚洲精品综合久久中文字幕| 国产激情综合五月久久| 午夜精品久久久久久久99黑人| 久久久久99精品久久久久| 亚洲国产精久久久久久| 欧美成人在线影院| 亚洲国产精彩中文乱码av在线播放| 久久久噜久噜久久综合| 日韩高清欧美高清| 欧美一区二区三区免费观看| 亚洲伊人久久综合| 91福利视频网| 中文字幕亚洲字幕| 国产日韩欧美在线看| 91视频免费在线| 欧美日韩国产限制| 国产一区二区三区网站| 亚洲无限乱码一二三四麻| 日韩中文字幕在线观看| 国产欧美日韩精品在线观看| 欧美在线中文字幕| 亚洲欧美另类人妖| 亚洲尤物视频网| 海角国产乱辈乱精品视频| 欧美亚洲国产视频小说| 夜夜躁日日躁狠狠久久88av| 亚洲视频在线播放| 九九九久久久久久| 国产精品第10页| 国产成+人+综合+亚洲欧洲| 久久精品免费电影| 日韩精品视频在线观看网址| 成人两性免费视频| 日韩中文字幕国产精品| 亚洲免费电影一区| 国产一区二区三区四区福利| 精品动漫一区二区| 日韩毛片在线看| 欧美日韩美女在线观看| 亚洲人成在线观看网站高清| 欧美国产极速在线| 91国产高清在线| 欧美精品videos| 亚洲欧美国产高清va在线播| 性亚洲最疯狂xxxx高清| 欧美大成色www永久网站婷| 亚洲欧美另类在线观看| 精品久久久久久亚洲国产300| 91在线观看欧美日韩| 久久久亚洲天堂| 九九热r在线视频精品| 日韩国产欧美精品在线| 91国偷自产一区二区三区的观看方式| 欧美激情视频播放| 日韩精品视频在线观看网址| 日韩av在线免费看| 91精品在线影院| 精品国偷自产在线视频| 91久久久久久国产精品| 亚洲一区二区三区视频播放| 国产精品久久久久久搜索| 国产精品三级美女白浆呻吟| 色综久久综合桃花网| 视频直播国产精品| 一个人看的www久久| 午夜精品久久久久久99热软件| 成人写真视频福利网| 91免费看片在线| 国产精品视频久久久久| 精品美女久久久久久免费| 亚洲精品资源美女情侣酒店| 国产精品视频成人| 在线视频亚洲欧美| 日本精品中文字幕| 久久99亚洲热视| 成人高清视频观看www| 精品中文字幕在线观看| 亚洲精品aⅴ中文字幕乱码| 欧美性猛交xxxx免费看漫画| 国产精品丝袜白浆摸在线| 国产日韩欧美中文在线播放| 久久人人爽人人爽人人片av高请| 亚洲美女av在线播放| 91免费看片网站| 亚洲国产天堂网精品网站| 国产日韩在线视频| 亚洲男人7777| 久久天天躁狠狠躁夜夜躁2014| 亚洲片av在线| 韩国三级电影久久久久久| 欧美日韩亚洲91| 国产91av在线| 日韩经典第一页| 久久久久久久久久久免费精品| 国产精品免费一区| 国产91精品在线播放| 国产成人福利视频| 亚洲国模精品私拍| 色综合天天综合网国产成人网| 国产精品久久久久久久久久久久久| 久久视频在线播放| 亚洲第一中文字幕在线观看| 奇米成人av国产一区二区三区| 日韩精品在线免费观看视频| 日韩大陆欧美高清视频区| 欧美激情中文网| 国模叶桐国产精品一区| 亚洲欧美日本伦理| 97**国产露脸精品国产| 国产精品爱啪在线线免费观看| 国内精品中文字幕| 亚洲精品资源美女情侣酒店| 欧美性理论片在线观看片免费| 成人久久久久久| 国产精品www| 欧美精品激情在线观看| 色偷偷亚洲男人天堂| 欧美高清videos高潮hd| 欧美性猛交xxxx免费看漫画| 成人福利网站在线观看| 亚洲第一中文字幕在线观看| 国产成人短视频| 亚洲色图13p| 国产91精品久久久久久| 欧美日韩国产一区在线| 欧美精品videos另类日本| 久久天天躁狠狠躁老女人| 日韩精品视频免费在线观看| 5566日本婷婷色中文字幕97| 欧美猛男性生活免费|