我一直都有这种困惑。如果我编写一个使用伪代码来断言某些操作的代码,那么当它真正使用真实对象而不是假对象时,我如何相信我的实际实现。
例如,我有这段代码 -
[Test]
public void CanCreateContactsWithData()
{
using(ISession session = factory.OpenSession())
using (ITransaction trans = session.BeginTransaction())
{
_contactId = (long) session.Save(contact);
trans.Commit();
}
Assert.AreNotEqual(0, _contactId);
}
此代码测试“联系”对象的实现,无论是否将其保存到数据库中。如果我碰巧使用存根而不是真正的数据库连接,我是否需要单独测试将其存储在数据库中?而且,你们称之为集成测试吗?
回答非常感谢。答案 0 :(得分:14)
Martin Fowler有一个很好的讨论here。
从他的文章:
Meszaros使用术语Test Double作为任何类型的假装对象的通用术语,用于代替真实对象进行测试。这个名字来自电影中特技双人的概念。 (他的目标之一是避免使用已广泛使用的任何名称。)Meszaros然后定义了四种特殊的双重类型:
在这些双打中,只有嘲讽坚持行为验证。
答案 1 :(得分:2)
您应该测试您编写的代码。如果您编写了数据库连接对象代码,那么请对其进行测试。否则,如果它是具有自己的测试的库的一部分,你可以模拟/存根它并假设如果连接对象通过它自己的测试套件,那么它可以工作。
例如,我不会测试对Hibernate方法的调用,我认为Hibernate开发人员已经对它进行了彻底的测试。但我会测试我正在调用正确的方法,使用模拟来设置期望值。
答案 2 :(得分:2)
当您只想要一个函数返回某个值(或什么都不做)时,您可以使用存根。你真的不关心函数是否被调用,你只想隔离事物。
模拟更强大,因为你可以跟踪函数是否被调用,多少次,甚至用你的函数获得的值来做事。
在您的情况下,如果您想模拟数据库(因此它变成单元测试而不是功能测试),您可以模拟ISession和ITransaction。然后,您可以将此值存储在内存中,并检查是否保存了正确的值。
答案 3 :(得分:0)
是的,根据您的定义,使用真实数据库将更具功能性或集成测试。就个人而言,我觉得单元测试应该只测试那种方法,而不是其他所有方法。因此,无论会话或事务是否有效,您的单元测试必须确保 这些对象在必要时被调用以进行工作 - 这就是模拟和存根进入的地方。使用它们来确保您的单元测试与外部功能分离,以便可以作为基本单元进行测试;理想情况下无论如何。
答案 4 :(得分:0)
大多数单元测试都是关于测试单个代码片段,而存根和模拟只是帮助您逐个测试的工具。通过单独测试各个部分,您可以更详细地测试每个部分,但不能保证完整图片的任何内容。各种集成测试都可以做到这一点。
在测试更大的功能时,我经常发现数据库逻辑的实际集成测试是最不重要的测试工件,因为您经常会在UI级别测试这些相同的操作。