我最近对测试非常感兴趣,我现在正在努力学习以最佳方式进行单元测试。我和Ninoit一起使用Rhino Mocks。我也在Stackoverflow上阅读了很多内容,但还没有找到我问题的明确答案。
我想知道如果我有一个类似下面的方法,我应该模拟OfficeClass依赖项并测试GetAllOffices或仅使用存根来获取依赖关系并验证方法GetAllOffices已被调用并且我确实获得了办公室从我对存根的设置中得到的回应?
public Offices GetAllOffices()
{
try
{
var offices = officeClass.GetAllOffices();
return offices;
}
}
如果OfficeClass只是另一个POCO,或者是否因为嘲弄和存根而被称为网络服务会不会有任何区别?
长问题简介:何时进行模拟以及何时在单元测试中使用Stub?
答案 0 :(得分:11)
模拟使用框架生成依赖项的“模拟”。例如,如果officeClass是数据的存储库,那么您可以使用模拟框架(我使用MOQ)生成存储库的模拟。这就是为什么使用接口使其成为测试的理想选择,模拟框架可以轻松地模拟测试接口。
根据我的理解,您可以手动删除依赖项并创建预设响应。例如,如果您有一个接口IOfficeClass并且您创建了一个继承自它的新类,则可以将该类注入您的服务以允许您使用它。
Web服务之类的东西应该包含在某个界面(如IRepository模式)中,这样您就可以轻松测试逻辑而无需点击Web服务。与POCO课程相同。
例如,在您的情况下,您将拥有:
public interface IOfficeRepository
{
IQueryable<Office> GetAll();
}
为您服务
public class MyOfficeService
{
private readonly IOfficeRepository officeRepostiory;
public MyOfficeService(IOfficeRepository repository)
{
this.officeRepostiory = repository;
}
public Office GetOffice(int id)
{
return this.officeRepostiory.GetAll().SingleOrDefault(o => o.Id == id);
}
}
通过这种方式,您还可以更改基础数据源,而无需修改主应用程序或业务逻辑代码。
您的单元测试使用moq看起来像这样:
[TestClass]
public class OfficeUnitTest
{
private MyOfficeService service;
[TestInitialize]
public void Setup()
{
var officeRepository = new Mock<IOfficeRepository>();
var office = new List<Office>();
office.Add(new Office{ Id = 1 });
officeRepository.Setup(m => m.GetAll()).Returns(office.AsQueryable());
this.service = new MyOfficeService(officeRepository.Object);
}
[TestMethod]
public void TestGetById()
{
Assert.IsNotNull(service.GetOffice(1));
// my mock will never return a value for 2
Assert.IsNull(service.GetOffice(2));
}
}
您可以在下面阅读有关模拟和存根的更多信息: