使用数据库时保持面向对象和可测试性


16

使用数据库但保持单元可测试性的一些OOP策略是什么?假设我有一个User类,并且我的生产环境适用于MySQL。我看到了两种可能的方法,如下所示使用PHP:

  1. 通过在与接口$ DATA_SOURCE load()save(),抽象数据的后端源。测试时,请传递其他数据存储。

    $ user =新用户($ mysql_data_source);
    $ user-> load('bob');
    $ user-> setNickname('Robby');
    $ user-> save();
    
  2. 使用访问数据库并将结果行传递给用户的构造函数的工厂。测试时,手动生成$ row参数,或在UserFactory :: $ data_source中模拟对象。(如何保存对记录的更改?)

    class UserFactory {
        static $data_source;
    
        public static function fetch( $username ) {
            $row = self::$data_source->get( [params] );
    
            $user = new User( $row );
            return $user;
        }
    }
    

我旁边有设计模式简洁代码,但我一直在努力寻找适用的概念。


Answers:


11

因此,您想了解的是Martin Fowlers的《企业应用程序体系结构模式》(他还在他的网站上提供了目录)。

他在其中描述了几种抽象数据访问的模式。您描述的第一种方法是Active Record。您的第二种方法类似于表数据网关

更好的方法是使用O / RM来消除手工编写数据访问代码的需要。由于我们担心Y2K,所以我没有使用过PHP,但是Wikipedia为您提供了一系列选项。我不知道他们有什么好处。我可以告诉您一些要在O / RM中查找的内容:

  • 持久性无知:O / RM不应强迫您的业务对象从特定的接口/类派生而参与数据访问策略。
  • 关系映射:您应该能够映射对象之间的关系(客户有订单,订单有订单项,订单项有产品等)
  • 层次映射:您应该能够将类层次映射到数据库。
  • 查询语法/条件支持:您应该能够在运行时根据对象而不是数据库来创建查询,O / RM应该转换并在数据库上运行查询。如果查询是强类型链而不是字符串,则需要加分。

还有其他因素需要考虑,但其中一些是最重要的。希望这可以帮助。


6

恕我直言,这取决于您要测试的内容,如果您要对业务逻辑进行单元测试,则应该对数据访问存根/模拟(Martin Fowler),所以您的第一个建议是个不错的开端。这个stackoverflow问题给出了一个不错的C#示例(我试图找到一些PHP示例,但找不到任何示例)。

如果您想测试数据访问本身,那么它就不再是单元测试,而是集成测试。阅读此处以获得一些一般性指导,这个stackoverflow问题也有一些有趣的链接。

如果要在数据库中测试存储过程逻辑,请查看xUnit TestPattern

希望这可以帮助



0

我建议您检查Symfony Framework解决此类问题的方法。Symfony是一个带有功能测试的php OO框架。

这是一个链接,他们使用了您正在考虑的东西。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.