【问题标题】:Stub vs Mock when unit testing [duplicate]单元测试时存根与模拟[重复]
【发布时间】:2014-03-29 02:52:13
【问题描述】:

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

我想知道如果我有一个像下面这样的方法,我应该模拟 OfficeClass 依赖项并测试 GetAllOffices 还是只对依赖项使用存根并验证 GetAllOffices 方法已被调用并且我确实得到了办公室回到我对存根设置的预期?

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

如果 OfficeClass 只是另一个 POCO,或者如果说它是一个 web 服务,在 mocking vs stubbing 的情况下会有什么不同吗?

简短的长问题:在单元测试中何时模拟和何时存根?

【问题讨论】:

  • 我之前一直在阅读那篇文章,但我仍然不确定何时使用其中一个而不是另一个,因此我认为在我自己的代码上下文中获得一些输入会有所帮助。
  • 不确定您在帖子中遗漏了什么 - 一切都在那里。它列出了这两个概念之间的所有差异。
  • 我仍然觉得我对“何时在单元测试中模拟和何时存根?”这个问题有了答案模拟以及何时我应该在单元测试的上下文中存根一个对象。

标签: c# unit-testing mocking stub


【解决方案1】:

Mocks 使用框架来生成依赖项的“模拟”。例如,如果 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);
    }
}

通过这种方式,您还可以更改底层数据源,而无需修改主应用程序或业务逻辑代码。

使用最小起订量,您的单元测试将如下所示:

[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

【讨论】:

  • 我认为 martinfowler 很好地解释了 DummyFake 这四种含义存根模拟。谢谢。
猜你喜欢
  • 2016-03-01
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 2010-12-22
  • 2011-07-11
  • 2021-01-23
  • 2020-03-24
  • 1970-01-01
相关资源
最近更新 更多