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

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

單元測試——使用模擬對象做交互測試

2019-11-14 14:27:38
字體:
供稿:網(wǎng)友

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

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

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

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);
   }
}

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

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;
        }
  }

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

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

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

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

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

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

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

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();
        }

  這里我沒有編寫一個類去繼承ILog接口,而是通過模擬框架,動態(tài)生成了一個ILog對象。代碼是這句:

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

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

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

  這里我們期望向日志中寫入用戶名。再通過回放來進(jìn)行驗證,代碼如下:

1
mock.VerifyAll();

  該方法會驗證,期望向日志中寫入的信息與實際向日志中寫入的信息是否一致,如果不一致,測試失敗。

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

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

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

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

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


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 庐江县| 响水县| 三明市| 宜昌市| 库尔勒市| 吉首市| 信阳市| 瑞安市| 全南县| 揭阳市| 高州市| 兰西县| 崇仁县| 汝南县| 顺昌县| 禄丰县| 灵川县| 平谷区| 互助| 荔波县| 桃园市| 灵璧县| 石棉县| 娄烦县| 夏邑县| 叶城县| 阳高县| 建昌县| 丹东市| 淮安市| 长泰县| 铅山县| 台东县| 贡嘎县| 桂平市| 定日县| 蒲城县| 左权县| 邓州市| 土默特左旗| 洛隆县|