同时结合使用模拟对象和桩对象
使用模拟对象要注意的
使用多个模拟对象就说明同时测试了多个事情,所以使用多个桩是可行的但是不能有多个模拟对象。
新需求
LogAnalyzer在WebService抛出错误时发送邮件
- 在文件名过短时调用WebService
- 在WebService抛出错误时发送电子邮件给管理员
- WebService作为桩,EmailService作为模拟对象进行测试
定义接口
WebService的接口
public interface IWebService
{
void LogError(string message);
}
EmailService的接口
public interface IEmailService
{
void SendEmail(string to, string subject, string body);
}
制作伪对象和桩
public class FakeWebService : IWebService
{
//存储交互数据
public string LastError;
//模拟抛出异常的情况
public Exception ToThrow;
public void LogError(string message)
{
LastError = message;
if (ToThrow != null)
{
throw ToThrow;
}
}
}
public class FakeEmailService : IEmailService
{
public string To;
public string Subject;
public string Body;
public void SendEmail(string to, string subject, string body)
{
To = to;
Subject = subject;
Body = body;
}
}
使用被测试类调用伪对象和桩
public class LogAnalyzerAll
{
//在构造时,把伪对象和桩注入进来
public LogAnalyzerAll(IWebService service, IEmailService email)
{
Email = email;
Service = service;
}
public IWebService Service { get; set; }
public IEmailService Email { get; set; }
public void Analyze(string fileName)
{
if (fileName.Length < 8)
{
try
{
Service.LogError("文件名太短:" + fileName);
}
catch (Exception e)
{
Email.SendEmail("someone@somewhere.com", "不能储存Log", e.Message);
}
}
}
}
测试代码
[TestFixture]
public class LogAnalyzerAllTest
{
[Test]
public void Analyze_WebServiceThrow_SendsEmail()
{
//做一个假的WebService并给其中的ToThrow赋值,以便测试抛出异常的状况
FakeWebService stubService = new FakeWebService();
stubService.ToThrow = new Exception("fake exception");
//模拟一个邮件服务
FakeEmailService mockEmail = new FakeEmailService();
LogAnalyzerAll log = new LogAnalyzerAll(stubService, mockEmail);
string tooShortFileName = "abc.ext";
log.Analyze(tooShortFileName);
//对模拟的邮件服务中的数据做断言,测试是否确实的抛出了对应的异常
StringAssert.Contains("someone@somewhere.com", mockEmail.To);
StringAssert.Contains("不能储存Log", mockEmail.Subject);
StringAssert.Contains("fake exception", mockEmail.Body);
//使用多个断言会产生问题,第一个失败了其他的都不执行了。
//通过创建EmailInfo对象,把要检验的三个属性都赋给它,就可以只用一个断言了(实际上不可以简单的使用Asert.AreEqual()来对两个对象作比较)。
}
}