外部依赖对象
对于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("[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用来判断测试通过还是失败
良好的产品代码才能单元测试
如果产品代码是下面那样,你就没办法测试了。 因为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/