• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 單元測試之Stub和Mock

    發表于:2015-09-21來源:uml.org.cn作者:不詳點擊數: 標簽:單元測試
    在做單元測試的時候,我們會發現我們要測試的方法會引用很多外部依賴的對象,比如:(發送郵件,網絡通訊,記錄Log, 文件系統 之類的)。 而我們沒法控制這些外部依賴的對象。 為了

      在做單元測試的時候,我們會發現我們要測試的方法會引用很多外部依賴的對象,比如:(發送郵件,網絡通訊,記錄Log, 文件系統 之類的)。 而我們沒法控制這些外部依賴的對象。 為了解決這個問題,我們需要用到Stub和Mock來模擬這些外部依賴的對象,從而控制它們

      實例

      Analyze類會檢查filename的長度,如果小于8,我們就會使用一個實現IWebService的類來記錄錯誤.

      我們需要給Analyze方法寫單元測試。

    public class LogAnalyzer
    {
        private IWebService service;
        private IEmailService email;
    
        public IWebService Service
        {
            get { return service; }
            set { service = value; }
        }
    
        public IEmailService Email
        {
            get { return email; }
            set { email = value; }
        }
    
        public void Analyze(string fileName)
        {
            if (fileName.Length < 8)
            {
                try
                {
                    service.LogError("the file name is to short" + fileName);
                }
                catch (Exception e)
                {
                    email.SendEmail("From@test.com", "To@test.com", "IWebServiceFailed", e.Message);
                }
            }
        }
    }

      設計測試用例

      測試用例一:

      fileName= "c:\test\test.txt" (長度大于8),

      期待測試結果: 不會發郵件

      測試用例二:

      fileName="c:\",(長度小于8), 并且記log失敗 。

      期待測試結果: 發郵件

      如果給Analyze方法寫單元測試,為了實現測試用例二。 這時候我們就會碰到兩個問題。

      第一: 我們無法控制讓Service對象記log時拋出異常. 因為Serveice對象我們無法控制

      第二: 我們無法判斷,Email對象是否發送了Email, (我們不能去Outlook查看收到郵件沒有,這樣就不是自動化了)

      外部依賴對象

      對于LogAnalyzer對象來說, Service和Email就是兩個外部依賴對象. 我們需要自己寫Stub和Mock來模擬這兩個外部依賴對象。這樣我們才能控制他們。

      我們在測試的代碼中新建StubWebService和MockEmailService.這兩個class分別實現了IWebService和IEmailService.

    public class StubWebService : IWebService
    {
        public void LogError(string message)
        {
            throw new Exception("StubWebService throw exception");
        }
    }
    
    public class MockEmailService : IEmailService
    {
        public string To;
        public string From;
        public string Subject;
        public string Message;
    
        public void SendEmail(string to, string from, string subject, string message)
        {
            To = to;
            From = from;
            Subject = subject;
            Message = message;
        }
    }

      工作流程圖如下

      最后我們來看看我們的測試代碼,

      我們把StubWebService和MockEmailService兩個類的實例注入到產品代碼中。(因為多態特性嘛)。

      通過控制StubWebService中的LogError方法,拋出一個異常。

      然后判斷MockEmailService中的SendEmail方法有沒有被調用. 被調用了說明發送了Email(我們不需要真的收到一封郵件,因為SendEmail功能是IEmailService實現的,)

    [TestMethod]
    public void TestMethod1()
    {
        StubWebService stubWebService = new StubWebService();
        MockEmailService mockEmailSender = new MockEmailService();
    
        LogAnalyzer log = new LogAnalyzer();
        log.Emailservice = mockEmailSender;
        log.WebService = stubWebService;
    
        // Act
        string tooShortFileName = "1.txt";
        log.Analyze(tooShortFileName);
    
        // Assert
        Assert.AreEqual("to@test.com", mockEmailSender.To);
        Assert.AreEqual("from@test.com", mockEmailSender.From);
        Assert.AreEqual("WebSerive log error", mockEmailSender.Subject);
    }

      Stub和Mock的相同處

      從上面的例子我們可以看出, Stub和Mock都是模擬外部依賴,以便我們能控制。

      Stub 和Mock 的區別

      Stub是完全模擬一個外部依賴, 而Mock用來判斷測試通過還是失敗

    原文轉自:http://www.uml.org.cn/Test/201210171.asp

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>