单元测试中的模拟对象

3

可能是重复问题:
硬编码模拟对象 vs 模拟框架

我认为我终于开始理解单元测试的意图,但仍然难以实现所有细节。我得出结论,我可能需要一个“模拟”(我轻松使用此术语,因为我不确定是否需要像 Moq 这样的整个框架)对象来完成工作。

作为 Repository Pattern(或类似模式)实现的示例。据我目前的理解,我至少需要对每个 Add()Get()Remove() 类方法进行测试。这很好,但是假设我想测试 Add() 方法如何处理 null 引用。在这种情况下,我是否只需在测试项目中定义一个简单的类,并将其实例设置为 null,然后在适当的单元测试中使用?

示例单元测试(说明):

[TestMethod]
public void TestAdd_Null()
{
    IRepository<MockObject> repository = (IRepository<MockObject>)(new Repository<MockObject>());
    MockObject testObject = null;

    repository.Add(testObject);

    Assert.IsNotNull(repository.Entity);
}

// I'm thinking I should implement something like this exclusively within the Test project.
// Is this reasonable? Or should I be looking into something else?
internal class MockObject
{
    public String Name { get; set; }
}

@Richard Szalay,这也可以工作。我使用MockObject的意图是表明我对模拟对象和预期使用的非常有限的理解。经过更多的研究,我开始觉得MockObject应该改为StubObject。我想我会等待并观察情况。 - Bradford Fisher
1个回答

1

我敢说,软件测试就像《黑客帝国》一样。没有人能告诉你软件测试是什么,你必须亲自去体验。大多数不信者从未给测试一个公正的机会,也从未尝试过进行一些测试。欢迎加入我们的行列!

然而,测试的棘手之处在于编写测试非常困难,有时编写可测试代码也具有挑战性。但是,今天有许多出色的工具和技术可以投资,以成为更好的软件工程师。

模拟提供了虚拟对象,否则您将不得不自己编写虚拟对象,模拟非常方便。在这种情况下,您的存储库不是实际的持久性服务,而只是提供要进行测试的合同。如果添加空引用不应该是可能的,则应该有一个测试用例来期望此操作失败。我相信这是不言而喻的,但测试这一点很重要。

Moq等库在这里非常有帮助,因为虚拟存储库什么都不做,您实际上希望进行断言。我不明白为什么需要在添加后有一个属性Entity(除了可能使编写测试更容易)。但我也认为这是断言预期行为的错误方式。

在某种程度上,你所做的实际上被称为集成测试,因为你不是在测试一个孤立的单元,而是使用模拟工厂来测试两个组件之间的交互。这些类型的测试非常重要,但如果它们没有被设计为可测试,则很难处理。这就是为什么我们有依赖注入等东西的原因。
你的问题并不需要具体的答案,但你正在正确的轨道上,并且我希望这将给你一些见解和额外的信心,在进行软件测试时。

谢谢您的见解。我已经阅读了一些关于Moq的内容,可以看出它在快速原型设计(每个测试几乎等同于可运行的伪代码)以及我想验证模拟对象的特定成员是否被调用或设置的情况下非常有用。然而,在许多测试场景中非常有用的是验证模拟对象成员内特定语句或调用的执行能力,但我没有找到这种功能。 - Bradford Fisher
为了进一步阐述这个想法...至少验证Add()方法中的特定语句是否执行(或更现实地说,到达例程中的特定点)以进行非空值(反之亦然)将是很好的。但是,我不确定当前在任何框架中实现了此功能(尽管我可能只是错过它)。 - Bradford Fisher
有这些记录/重放习惯用语,Moq 没有使用甚至声称不必要,我还没有深入研究,但也许也值得一试。 - John Leidegren
我研究了Record/Replay并发现它是构建和验证模拟的一种模式。Rhinomocks使用Record/Replay,而Moq使用Assemble/Act/Assert来完成相同的事情。所以,我想这是一个无意义的争论。然而,经过进一步的思考,我认为模拟存储库可能并不是一个好主意,因为那实际上是我试图测试的对象。但是,我还没有想出如何在不将模拟对象存储在某个地方的情况下验证添加方法是否真正发生了任何事情。 - Bradford Fisher
请原谅我这个直接的问题,但是你想再次测试什么? - John Leidegren
@John Leidegren 我意识到我也有点跑题了。对此我感到抱歉。如果您感兴趣,我已经创建了一个新问题,并更好地解释了问题:https://dev59.com/lFfUa4cB1Zd3GeqPMu5f。 - Bradford Fisher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接