单元测试时Stub vs Mock

时间:2014-02-26 10:32:37

标签: c# unit-testing mocking stub

我最近对测试非常感兴趣,我现在正在努力学习以最佳方式进行单元测试。我和Ninoit一起使用Rhino Mocks。我也在Stackoverflow上阅读了很多内容,但还没有找到我问题的明确答案。

我想知道如果我有一个类似下面的方法,我应该模拟OfficeClass依赖项并测试GetAllOffices或仅使用存根来获取依赖关系并验证方法GetAllOffices已被调用并且我确实获得了办公室从我对存根的设置中得到的回应?

public Offices GetAllOffices() 
{
    try
    {
        var offices = officeClass.GetAllOffices();
        return offices;
    }
}

如果OfficeClass只是另一个POCO,或者是否因为嘲弄和存根而被称为网络服务会不会有任何区别?

长问题简介:何时进行模拟以及何时在单元测试中使用Stub?

1 个答案:

答案 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));
    }
}

您可以在下面阅读有关模拟和存根的更多信息:

http://martinfowler.com/articles/mocksArentStubs.html

http://msdn.microsoft.com/en-us/library/ff649690.aspx