什么是嘲弄呢?

时间:2012-01-05 06:43:51

标签: mocking

我阅读了很多有关SOF和谷歌搜索结果的文章。

仍未弄清楚嘲弄的价值。

来自SOF之一的帖子: What is Object Mocking and when do I need it?

对象模拟用于保持单元测试之外的依赖关系。有时你会有像“SelectPerson”这样的测试,它会从数据库中选择一个人并返回一个Person对象。

  

为此,您通常需要依赖数据库,   然而,通过对象模拟,您可以模拟与...的交互   具有模拟框架的数据库,因此它可能返回一个数据集   看起来像是从数据库返回的,然后你可以测试你的   代码,以确保它处理将数据集转换为人   对象,而不是用它来测试与数据库的连接   存在。

以上示例也存在于许多Google搜索结果中,如此(Code Walkthrough部分) http://quickduck.com/blog/2008/02/18/unit-testing-mocking-and-dependency-injection/

但它只是导致单元测试断言的100%成功方法,因为我们设计了模拟方法&接口必须满足TestCase。 它不能在测试中失败,它与现实世界的数据库不同。

2 个答案:

答案 0 :(得分:0)

Mocking背后的基本概念可以帮助开发人员独立于其他代码单元或任何与DB,文件系统或服务的外部连接来测试他的代码(他的业务逻辑)。

代码应该设计为可测试性,如果实现了这一点,那么开发人员就知道他将从他的CUT(被测试类)所依赖的接口获得什么值。在您的情况下,开发人员应该知道将从数据库返回什么值。他应该只关心检查这些数据(从数据库返回)是否按照他实施的代码中的要求进行处理。

使所有测试通过的条件称为Over Mocking,这是因为对Test Doubles缺乏了解而引起的。对于您的特定情况,如果您对测试查询感兴趣并且对测试应用程序逻辑如何处理返回值不感兴趣,那么您可以尝试使用一些更快的内存数据库,如HSQLDB或H2。通过这种方式,您可以增加单元测试的范围。但是许多开发人员宁愿尝试在集成测试中测试这些查询,而不是单元测试。在实际术语中,当您使用真实数据库来测试代码时,它就不再是单元测试了。

要添加一个信息,如果查询数据库,则根据情况,您可以在结果集中返回一个或多个对象或不返回任何对象。因此,您可以配置模拟/存根以返回其中一个值。当你使模拟抛出一个异常,如“找不到结果”,那么这将是一个负面的情况。

答案 1 :(得分:0)

以此类/方法为例:

class Foo {

    ...

    public static function instantiateFromDb(Database $db, $id) {
        $record = $db->query("SELECT * FROM table WHERE id = $id");
        $foo = new self;
        $foo->id = $record['id'];
        ...
        $foo->initialize();
        $foo->calibrate();
        return $foo;
    }

    ...

}

Foo::instantiateFromDb是一种有点复杂的方法,用于从数据库记录中实例化对象(是的,这主要是伪代码)。为此,它取决于数据库对象,它用于从数据库中获取条目。因此,要测试此方法,您需要一个包含记录的数据库。这是一个非常大的依赖。您需要启动并运行数据库,需要与其建立连接,需要使用正确的数据填充数据库,您需要希望它不会停止运行。当你想做的只是测试Foo::instantiateFromDb方法时,它是一个依赖于大量移动部件的。

所以你要做的就是模仿Database对象。

public function testInstantiationFromDatabase() {
    $mockDb = new Mock('Database');

    prepare $mockDb so it always returns a valid record
    when its query() method is called...

    $this->assertInstanceOf('Foo', Foo::instantiateFromDb($mockDb, 1));
}

通过使用您知道的对象模拟数据库(因为它只执行一个特定的事情:返回有效记录),您已经从等式中获得了巨大的依赖性,并且可以专注于仅测试您实际想要的方法测试