天天看点

单元测试之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/

继续阅读