何时使用存根和模拟?

发布于 2024-08-02 22:00:41 字数 571 浏览 4 评论 0原文

我一直有这样的困惑。如果我编写一个使用假代码来断言某些操作的代码,那么当它真正使用真实对象而不是假对象启动时,我如何信任我的真实实现。

例如,我有这段代码——

    [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);
    }

这段代码测试“联系人”对象的实现,无论该对象是否保存到数据库中。如果我碰巧使用存根而不是真正的数据库连接,我是否需要进行单独的测试以将其存储在数据库中?而且,你们称之为集成测试吗?

衷心感谢您的回答。

I've this confusion all the time. If I write a code which uses fake code to assert some operation, how do i trust my real implementation when it is started really using the real objects instead of fake ones.

For example, I've this code --

    [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);
    }

This code tests the implementation of a "contact" object whether that gets saved into database or not. If i happened to use a stub instead of a real database connection, do I need to have separate test for storing it in database? And, do you guys call that as integration testing?

Answers are sincerely appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

葬花如无物 2024-08-09 22:00:41

Martin Fowler 在此处进行了很好的讨论。

来自他的文章:

Meszaros 使用术语“测试替身”作为用于代替真实对象进行测试目的的任何类型假装对象的通用术语。这个名字来源于电影中特技替身的概念。 (他的目标之一是避免使用任何已经广泛使用的名称。)Meszaros 然后定义了四种特殊类型的 double:

  • 虚拟对象被传递但从未实际使用。通常它们仅用于填充参数列表。
  • 假对象实际上有工作实现,但通常采取一些捷径,这使得它们不适合生产(内存数据库就是一个很好的例子)。
  • 存根为测试期间拨打的电话提供预设答案,通常根本不响应测试编程之外的任何内容。存根还可以记录有关呼叫的信息,例如记住它“发送”的消息的电子邮件网关存根,或者可能只记录它“发送”的消息数量。
  • 模拟就是我们在这里讨论的:用期望预先编程的对象,形成它们期望接收的调用的规范。

在这些类型的双打中,只有模拟坚持行为验证。

Martin Fowler has a good discussion here.

From his article:

Meszaros uses the term Test Double as the generic term for any kind of pretend object used in place of a real object for testing purposes. The name comes from the notion of a Stunt Double in movies. (One of his aims was to avoid using any name that was already widely used.) Meszaros then defined four particular kinds of double:

  • Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
  • Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
  • Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
  • Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.

Of these kinds of doubles, only mocks insist upon behavior verification.

水中月 2024-08-09 22:00:41

当您只想让函数返回一些值(或不执行任何操作)时,可以使用存根。您并不真正关心该函数是否被调用,您只是想隔离事物。

模拟更强大,因为您还可以跟踪函数是否被调用、调用了多少次,甚至可以使用函数获取的值进行操作。

在您的情况下,如果您想模拟数据库(因此它成为单元测试而不是功能测试),您可以模拟 ISession 和 ITransaction。然后,您可以将此值存储在内存中,并检查是否保存了正确的值。

You use stubs when you just want a function to return some value (or do nothing). You don't really care if the function was called or not, you just want to isolate things.

Mocks are more powerful, as you can also keep track if the function was called, how many times, and even do things with values your function gets.

In your case, if you want to mock the database (so it becomes a unit test rather than a functional one), you can mock ISession and ITransaction. You could then store this values in-memory, and check if the correct values were saved.

星星的軌跡 2024-08-09 22:00:41

您应该测试您编写的代码。如果您编写了数据库连接对象代码,请对其进行测试。否则,如果它是具有自己测试的库的一部分,您可以模拟/存根它并假设如果连接对象通过了它自己的测试套件,那么它就可以工作。

例如,我不会测试对 Hibernate 方法的调用,我假设 Hibernate 开发人员已经对此进行了彻底的测试。但我测试我是否调用了正确的方法,使用模拟来设置该期望。

You should be testing the code that you have written. If you wrote the database connection object code, then test it. Otherwise if it is part of a library with it's own tests, you can just mock/stub it and assume that if the connection object passes it's own test suite, then it works.

For example, I wouldn't test calls to Hibernate methods, I assume the Hibernate developers have thoroughly tested that already. But I would test that I was calling the correct method, using a mock to set up that expectation.

无人接听 2024-08-09 22:00:41

是的,使用真实的数据库会更具功能性或集成测试,具体取决于您的定义。就我个人而言,我认为单元测试应该只测试该方法,而与其他所有内容隔离。因此,无论会话或事务是否有效,您的单元测试都必须确保这些对象将在必要时被调用来完成其工作 - 这就是模拟和存根的用武之地。使用它们来确保您的单元测试与外部功能解耦,以便可以将其作为基本单元进行测试;无论如何,理想情况下。

Yes, using a real database would be more functional or integration testing, depending on your definition. Personally, I feel that unit tests are supposed to test exactly that method only, in isolation of everything else. So regardless of whether the session or the transaction works or not, your unit test must ensure that those objects will be called upon to do their work when and as necessary - that's where mocks and stubs come in. You use them to ensure that your unit test is as decoupled from external functionality so that it can be tested as a basic unit; ideally anyway.

感受沵的脚步 2024-08-09 22:00:41

大多数类型的单元测试都是关于测试各个代码段,而存根和模拟只是帮助您逐段测试的工具。通过单独测试各个部分,您可能可以更详细地测试每个部分,但不能保证您的整体情况。各种集成测试都可以做到这一点。

当测试较大的功能时,我经常发现数据库逻辑的实际集成测试是最不有价值的测试工件,因为您通常会在 UI 级别测试这些相同的操作。

Most kinds of unit testing is about testing individual pieces of code, and stubs and mocks are simply tools that assist you in testing piece-by-piece. By testing pieces individually you can probably test each piece in greater detail, but you will not be guaranteed anything about the full picture. Various kinds of integration testing will do that.

When testing bigger pieces of functionality, I often find actual integration tests of database logic to be the least valuable test artifacts, since you will often be testing these same operations at the UI level.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文