天天看點

單元測試之Stub和Mock

 外部依賴對象

  對于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;

  工作流程圖如下

單元測試之Stub和Mock

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

  我們把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("[email protected]", mockemailsender.to);

assert.areequal("[email protected]", mockemailsender.from);

assert.areequal("webserive log error", mockemailsender.subject);

  stub和mock的相同處

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

  stub 和mock 的差別

  stub是完全模拟一個外部依賴, 而mock用來判斷測試通過還是失敗

單元測試之Stub和Mock
單元測試之Stub和Mock

  良好的産品代碼才能單元測試

單元測試之Stub和Mock
單元測試之Stub和Mock
單元測試之Stub和Mock

  如果産品代碼是下面那樣,你就沒辦法測試了。 因為webservice和emailservice兩個類沒有繼承接口。我們無法把stubwebservice和mockemailservice兩個類注入到産品代碼。

public class loganalyzer

private webservice webservice;

private emailservice emailservice;

public webservice webservice

get { return webservice; }

set { webservice = value; }

public emailservice emailservice

get { return emailservice; }

set { emailservice = value; }

public void analyze(string filename)

if (filename.length < 8)

try

webservice.logerror("filename too short:" + filename);

catch (exception e)

emailservice.sendemail("[email protected]", "[email protected]", "webserive log error", e.message);

  mock架構

  其實我們沒有必要自己寫mockemailservice方法。  已經有現成的mock架構可以用了, .net中有rhino mock 和 moq,  這兩個架構比較好用

最新内容請見作者的github頁:http://qaseven.github.io/

繼續閱讀