国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

單元測(cè)試——使用模擬對(duì)象做交互測(cè)試

2019-11-14 14:17:14
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

最近在看.net單元測(cè)試藝術(shù),我也喜歡單元測(cè)試,這里寫(xiě)一下如何在測(cè)試中使用模擬對(duì)象。

     開(kāi)發(fā)的過(guò)程中,我們都會(huì)遇到對(duì)象間的依賴(lài),比如依賴(lài)數(shù)據(jù)庫(kù)或文件,這時(shí),我們需要使用模擬對(duì)象,來(lái)進(jìn)行測(cè)試,我們可以手寫(xiě)模擬對(duì)象,當(dāng)然也可以使用模擬框架。

     假如有這樣的一個(gè)需求,當(dāng)用戶(hù)登陸時(shí),我需要對(duì)用戶(hù)名和密碼進(jìn)行驗(yàn)證,然后再將用戶(hù)名寫(xiě)入日志中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyLogin
    {
        public ILog Log { getset; }
  
        public bool Valid(string userName, string passWord)
        {
            var isValid = userName == "admin" && passWord == "123456";
 
            Log.Write(userName);
 
            return isValid;
        }
    }
 
    public interface ILog
    {
        void Write(string message);
   }
}

     上面的代碼在驗(yàn)證完登陸信息后,需要向日志中寫(xiě)入用戶(hù)名,由于寫(xiě)入日志可能依賴(lài)于文件或數(shù)據(jù)庫(kù),我們可能很難進(jìn)行測(cè)試,所以,這里使用模擬對(duì)象進(jìn)行測(cè)試。手寫(xiě)模擬對(duì)象,代碼如下:

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
[TestFixture]
    public class MyLoginTest
    {
        [Test]
        public void Vaild_Test()
        {
            MyLogin login = new MyLogin();
  
            var log = new TestLog();
  
            login.Log = log;
 
            var userNmae = "admin";
 
            var passWord = "123456";
 
            var isLogin = login.Valid(userNmae, passWord);
 
            Assert.AreEqual(isLogin, true);
 
            Assert.AreEqual(log.Message, userNmae);
        }
   }
    public class TestLog : ILog
    {
        public string Message;
 
        public void Write(string message)
        {
            this.Message = message;
        }
  }

     這里我們定義了一個(gè)對(duì)象TestLog對(duì)象,該對(duì)象就是一個(gè)模擬對(duì)像,繼承了ILog接口。該測(cè)試中,一共進(jìn)行了兩項(xiàng)測(cè)試。一項(xiàng)是:驗(yàn)證用戶(hù)名和密碼是否輸入正確。另一項(xiàng)是:驗(yàn)證用戶(hù)寫(xiě)入日志的信息是否正確(比如應(yīng)該寫(xiě)入用戶(hù)名,結(jié)果把密碼寫(xiě)入了日志,測(cè)試會(huì)無(wú)法通過(guò))。

     這里我們區(qū)分一下模擬對(duì)象與樁對(duì)象。上一節(jié)中,我們講過(guò)樁對(duì)象的定義,那么模擬對(duì)象與樁對(duì)象是什么關(guān)系呢?

     模擬對(duì)象與樁對(duì)象在寫(xiě)法上區(qū)別很小,關(guān)鍵在于模擬對(duì)象需要進(jìn)行斷言,也就是說(shuō)模擬對(duì)象可以導(dǎo)致測(cè)試失敗。樁對(duì)象只是為了方便測(cè)試所定義的一個(gè)對(duì)象,不需要進(jìn)行斷言,所以,樁對(duì)象永遠(yuǎn)不會(huì)導(dǎo)致測(cè)試失敗。

     上面的測(cè)試中,如果我們?nèi)サ糇詈笠恍写a,即我們不進(jìn)行寫(xiě)入日志的斷言,則該對(duì)象就是一個(gè)樁對(duì)象。

1
Assert.AreEqual(log.Message, userNmae);

  上面的模擬對(duì)象是我們自己寫(xiě)的,自己寫(xiě)模擬對(duì)象比較費(fèi)時(shí),我們可以使用模擬框架進(jìn)行編寫(xiě)。這里我使用了Rhino Mocks框架。如果要執(zhí)行下面的代碼,需要下載Rhino.Mocks.dll文件,然后直接引用即可。

測(cè)試框架這里我選用了NUnit框架。測(cè)試代碼如下:

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
[TestFixture]
    public class MyLoginTest
    {
        [Test]
         public void Mock_Vaild_Test()
        {
            MockRepository mock = new MockRepository();
 
            var log = mock.DynamicMock<ILog>();
 
            var userName = "admin";
 
            var passWord = "123456";
 
            using (mock.Record())
            {
                log.Write(userName);
            }
 
            MyLogin login = new MyLogin();
 
            login.Log = log;
 
            var isLogin = login.Valid(userName, passWord);
 
            Assert.AreEqual(isLogin, true);
 
            mock.VerifyAll();
        }

  這里我沒(méi)有編寫(xiě)一個(gè)類(lèi)去繼承ILog接口,而是通過(guò)模擬框架,動(dòng)態(tài)生成了一個(gè)ILog對(duì)象。代碼是這句:

1
2
3
MockRepository mock = new MockRepository();
 
var log = mock.DynamicMock<ILog>();

  這里便生成了Log對(duì)象。通過(guò)錄制-回放的模式進(jìn)行模擬對(duì)象測(cè)試,首先需要定義我們的期望行為,最后驗(yàn)證實(shí)際行為與期望行為是否一致。這里,需要錄制我們期望行為,代碼如下:

1
2
3
4
using (mock.Record())
     {
         log.Write(userName);
     }

  這里我們期望向日志中寫(xiě)入用戶(hù)名。再通過(guò)回放來(lái)進(jìn)行驗(yàn)證,代碼如下:

1
mock.VerifyAll();

  該方法會(huì)驗(yàn)證,期望向日志中寫(xiě)入的信息與實(shí)際向日志中寫(xiě)入的信息是否一致,如果不一致,測(cè)試失敗。

  這里我們便完成了使用模擬框架進(jìn)行單元測(cè)試。如果我們不需要測(cè)試日志寫(xiě)入方法,則把模擬對(duì)象換成樁對(duì)象就可以了,生成樁對(duì)象的方法如下:

1
2
3
MockRepository mock = new MockRepository();
 
var log = mock.Stub<ILog>();

把回放的方法(mock.VerifyAll())去掉,就完成了模擬對(duì)象向樁對(duì)象的轉(zhuǎn)變。注意,這里錄制的代碼還是需要的。

總結(jié):編寫(xiě)模擬對(duì)象和樁對(duì)象是非常有意義的,使用框架可以幫助我們簡(jiǎn)化單元測(cè)試。一般情況下,一個(gè)測(cè)試中,可以有多個(gè)樁對(duì)象,但最好只有一個(gè)模擬對(duì)象。模擬對(duì)象太多,證明一個(gè)測(cè)試方法做了太多項(xiàng)測(cè)試,不利于維護(hù)測(cè)試代碼,一旦代碼變改,很容易使單元測(cè)試失敗。

下一節(jié),寫(xiě)一下測(cè)試框架的一些常用功能,如:如何模擬異常、如何模擬返回值等。。。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 广西| 卢氏县| 石林| 凤城市| 濮阳县| 平顶山市| 泰州市| 九江市| 繁峙县| 扶风县| 嘉鱼县| 凤庆县| 阜康市| 静宁县| 迁西县| 察雅县| 延长县| 百色市| 桐城市| 精河县| 合江县| 西贡区| 虞城县| 公安县| 宁乡县| 沐川县| 双牌县| 弋阳县| 桑植县| 驻马店市| 海淀区| 宜良县| 花垣县| 吴堡县| 山东省| 澄城县| 新疆| 宜宾县| 会同县| 奉化市| 广德县|