我应该在Data Mapper中对单元测试和DBUnit测试进行类似的测试吗?

时间:2015-03-16 21:33:07

标签: php unit-testing dbunit

我一直在练习和阅读有关测试驱动开发的内容。 到目前为止,我一直表现不错,因为很多内容很简单,但我对测试内容有疑问 关于某些类,例如下面的类。

    public function testPersonEnrollmentDateIsSet()
    {
        //For the sake of simplicity I've abstracted the PDO/Connection mocking
        $PDO = $this->getPDOMock();
        $PDOStatement = $this->getPDOStatementMock();

        $PDO->method('prepare')->willReturn($PDOStatement);
        $PDOStatement->method('fetch')->willReturn('2000-01-01');

        $AccountMapper = $this->MapperFactory->build(
            'AccountMapper',
            array($PDO)
        );

        $Person = $this->EntityFactory->build('Person');
        $Account = $this->EntityFactory->build('Account');
        $Person->setAccount($Account);
        $AccountMapper->getAccountEnrollmentDate($Person);

        $this->assertEquals(
            '2001-01-01',
            $Person->getAccountEnrollmentDate()
        );
    }

我有点不确定我是否应该完全测试这个有两个原因。

单元测试逻辑

在上面的示例中,我测试是否正确映射了值。仅仅是逻辑,嘲笑连接所以没有数据库。这很棒,因为我可以在没有任何其他开发人员安装或配置数据库依赖关系的情况下运行专有业务逻辑的测试。

DBUnit测试结果

但是,可以根据需要运行单独的配置来测试SQL查询本身,这是另一种类型的测试。同时还整合SQL测试以与单元测试分开运行。

测试与上述完全相同,但PDO连接不会被模拟出来并且是真正的数据库连接。

引起关注

我被撕裂了,因为虽然它正在测试不同的东西,但它本质上是重复的代码。

如果我摆脱单元测试,我会一直引入所需的数据库依赖。随着代码库的增长,测试将随着时间的推移变得更加缓慢,没有开箱即用的测试;其他开发人员为设置配置而付出的额外努力。

如果我摆脱了数据库测试,我无法确保SQL会返回预期的信息。

我的问题是:

这是保留两项测试的合理理由吗?

值得吗,还是可能会成为维护噩梦?

2 个答案:

答案 0 :(得分:0)

根据您的评论,您似乎想要测试PDO正在做什么。 (是prepareexecute等......被正确调用并做我期望的事情吗?)

这不是你想要在单元测试中做的事情。您不想测试PDO或任何其他库,并且您不应该测试PDO的逻辑或行为。确保PDO的负责人已完成这些工作。

您要测试的是正确执行您的代码以及您的代码的逻辑。您想要测试getAccountExpirationDate,以及您期望的结果。不是您期望从PDO调用的结果。

因此,如果我理解您的代码是正确的,您只需要测试您作为参数提供的$Person的到期日期是否已使用$result的预期值设置 - >如果你没有以正确的方式使用PDO,那么测试无论如何都会失败!

正确的测试可能是:

  • 创建UserMapper对象并打开数据库事务
  • 在将在$result
  • 中检索的数据库中插入数据
  • 使用正确的PersontaxId创建一个clientID对象,以便从您的查询中获取所需的$result
  • 运行UserMapper->getAccountExpirationDate($Person)
  • 断言 $Person->expirationDate等于$result
  • 所预期的结果
  • 回滚数据库事务

您还可以检查日期的格式等等......与您实施的逻辑相关的任何内容。

如果要在许多测试中测试此类内容,请在每次测试后使用setUptearDown初始化并回滚数据库。

答案 1 :(得分:0)

这是保留两项测试的合理理由吗?

我认为没有人能够从你的简单例子中说出你需要保留哪个测试。如果你愿意,你可以保留两者。我这样说是因为答案很大程度上取决于你项目的未知因素,包括未来的要求和修改

就我个人而言,我认为你不需要两者,至少对于同一个功能。如果您的函数在逻辑上比数据敏感更容易破解,请随意删除数据库支持的函数。随着时间的推移,您将学会使用正确类型的测试。

  1. 我被撕裂了,因为虽然它正在测试不同的东西,但它本质上是重复的代码。
  2. 是的,是的。

    1. 如果我摆脱了数据库测试,我无法保证SQL会返回预期的信息。
    2. 如果您的数据库变得足够复杂,这是一个有效的关注点。您正在使用DBUnit,因此我假设您有一个包含样本信息的示例数据库。随着时间的推移,生产数据库可能会进行多个结构修改(添加字段,删除字段,甚至重新处理数据关系......)。这些因素将增加您维护测试数据库的努力。但是,如果您意识到数据库中的某些更改不正确,那么也会有所帮助。

      1. 如果我摆脱单元测试,我会一直引入所需的数据库依赖。随着代码库的增长,测试将随着时间的推移变得更加缓慢,没有开箱即用的测试;其他开发人员为设置配置而付出的额外努力。
      2. 要求数据库依赖性有什么问题?

        首先,我不知道其他开发人员如何在此处设置配置。你只设置了一次,不是吗?在我看来,这是一个次要因素。

        其次,测试会随着时间的推移而变慢。当然。您可以指望内存数据库(如H2HSQLDB)来降低风险,但肯定需要更长时间。但是,你真的需要担心吗?大多数这些数据支持的测试都是集成测试。他们应该是Continuous Integration Server的责任,他们时不时地进行疲惫的测试以防止回归错误。对于开发人员来说,我认为我们应该只在开发过程中进行一小组轻量级测试。

        最后,我想提醒您使用单元测试的第1条规则: 测试可以破解的内容 。不要为了测试而编写测试。你永远不会有100%的报道。但是,由于80%的时间都使用了20%的代码,因此将测试工作重点放在主要业务流程上可能是一个好主意。