Php 如何对业务逻辑和数据访问代码进行单元测试

Php 如何对业务逻辑和数据访问代码进行单元测试,php,database,unit-testing,Php,Database,Unit Testing,我在一个PHP项目中工作,在那里测试软件被忽视了很长一段时间。 业务逻辑充满了硬编码的依赖关系,并通过一些手工编制的(Oracle)SQL立即访问数据库 我已经放弃尝试构建自动化集成测试,因为复杂的数据库设置、对(复杂的)数据库夹具的严格编译以及缺少内存中的解决方案 对我来说,最好的开始是测试业务逻辑。因此,我想我需要重构代码,使数据访问代码与业务逻辑分离。但我仍在苦苦思索一些基本的设计问题: 封装/摆脱这种复杂SQL的首选方法是什么是否有任何设计模式对如何以可配置的方式从数据源获取数据有一些好

我在一个PHP项目中工作,在那里测试软件被忽视了很长一段时间。 业务逻辑充满了硬编码的依赖关系,并通过一些手工编制的(Oracle)SQL立即访问数据库

我已经放弃尝试构建自动化集成测试,因为复杂的数据库设置、对(复杂的)数据库夹具的严格编译以及缺少内存中的解决方案

对我来说,最好的开始是测试业务逻辑。因此,我想我需要重构代码,使数据访问代码与业务逻辑分离。但我仍在苦苦思索一些基本的设计问题:

  • 封装/摆脱这种复杂SQL的首选方法是什么是否有任何设计模式对如何以可配置的方式从数据源获取数据有一些好的提示?在某些情况下,注入活动查询对象似乎是有帮助的,但在复杂的情况下,我想很难模仿它们
  • 对于那些需要大量使用数据库的应用程序,是否有一本关于软件体系结构+单元测试的好书

  • 回答你的第二个问题:这是你需要的:它解释了几种模式来打破依赖关系,使代码可测试

    关于你的第一个问题:这取决于你目前的情况。以下是本书中深入描述的几个示例:

    示例1-提取和覆盖调用

    如果您有一个类似的类(示例不是用php编写的,但您会明白的)

    示例2-参数化构造函数

    如果你有这样的课

    class MyClass {
        private IDbReader _reader;
    
        MyClass(){
           _reader = new DbReader();
        }
    
        int work(){
           List<item> items = _reader.read();
           //Work with items
        }
    }
    
    因此,在测试中模拟db是可能的


    所以,简而言之:有很多技术可以帮助你解决这个问题。我们需要一些更具体的代码。我建议阅读这本书,因为它在这些情况下提供了很多答案。

    为了清楚起见,上面的代码示例是用Java编写的,而不是用PHP编写的。它在PHP中的工作方式相同,语法略有不同。
    class TestableMyClass : MyClass {
        override List<Item> readInDb(){
           //Return a list of hard code test items
        }
    }
    
    class MyClass {
        private IDbReader _reader;
    
        MyClass(){
           _reader = new DbReader();
        }
    
        int work(){
           List<item> items = _reader.read();
           //Work with items
        }
    }
    
        MyClass() : this(new DbReader()){ }
    
        MyClass(IDbReader reader){
           _reader = reader;
        }