php - 测试具有内部函数调用的函数

标签 php phpunit

我是一个单元测试初学者,似乎陷入了如何对包含内部函数调用的函数进行单元测试的困境。例如,测试以下内容:

public function getBlueFooCount($fooId) {
   $foo = $fooDao->getFoosById($fooId);

   // custom logic to pull out the blue foos from result set
   // custom count business logic on blue foos ...

   return $count;
}

我如何能够模拟内部函数检索的内容?这是因为功能耦合太紧,需要放松一下吗?

最佳答案

为了构建@aib的答案,当我们开始对遗留代码库进行单元测试时,我们的大多数类都非常紧密地耦合,并且许多方法本身正在实例化新对象。虽然我们已采取措施实现 Dependency InjectionInversion of Control展望 future ,我们仍然受制于数百个仍需要单元测试的类。

在为遗留方法编写单元测试时,我们重构并将实例化为一个新的小方法,然后我们可以 stub 。不是最好的模式,但它很便宜并且无需进行更大的重构即可完成工作。

class FooCounter {

    public function getFooDao(){
        return new FooDao();
    }

    public function getBlueFooCount($fooId) {
        /* was this
        $fooDao = new FooDao();
        */
        $foo = $this->getFooDao()->getFoosById($fooId);

        // custom logic to pull out the blue foos from result set
        // custom count business logic on blue foos ...

        return $count;
    }

}

class FooCounterTest extends PHPUnit_Framework_TestCase {

    public function test_getBlueFooCount(){
        $fooCounter = $this->getMock('FooCounter', array('getFooDao'));
        $fooCounter->expects($this->any())
                   ->method('getFooDao')
                   ->will($this->returnValue(new MockFooDao()));

        $this->assertEquals(0, $fooCounter->getBlueFooCount(1));
    }

}

如果我们要实现一个新类,我们通常会使用基于构造函数的 DI,如果您要创建新的东西,这就是我将给出的答案。这是其他人的链接,因为我相信之前已经说过更好了(有点干):Dependency Injection and Unit Testing 。以及每个案例的一些示例:

基于构造函数的注入(inject)

class FooCounter {

    private $_fooDao

    public function __construct($fooDao){
        $this->_fooDao = $fooDao
    }

    public function getBlueFooCount($fooId) {
        $foo = $this->_fooDao->getFoosById($fooId);

        // custom logic to pull out the blue foos from result set
        // custom count business logic on blue foos ...

        return $count;
    }

}

class FooCounterTest extends PHPUnit_Framework_TestCase {

    public function test_getBlueFooCount(){
        $fooCounter = new FooCounter(new MockFooDao());

        $this->assertEquals(0, $fooCounter->getBlueFooCount(1));
    }

}

基于 Setter 的注入(inject)

class FooCounter {

    private $_fooDao

    public function setFooDao($fooDao){
        $this->_fooDao = $fooDao
    }

    public function getBlueFooCount($fooId) {
        $foo = $this->_fooDao->getFoosById($fooId);

        // custom logic to pull out the blue foos from result set
        // custom count business logic on blue foos ...

        return $count;
    }

}

class FooCounterTest extends PHPUnit_Framework_TestCase {

    public function test_getBlueFooCount(){
        $fooCounter = new FooCounter();
        $fooCounter->setFooDao(new MockFooDao());

        $this->assertEquals(0, $fooCounter->getBlueFooCount(1));
    }

}

关于php - 测试具有内部函数调用的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5761454/

相关文章:

php - 在 Laravel 测试用例中模拟一个 http 请求并解析路由参数

php - Doctrine 返回 null 代替 EntityNotFoundException

php - Laravel Blade 模板@extends

javascript - Bootstrap Accordion 被迫显示打开的 Accordion

php - 在图像中为验证码创建随机曲线

testing - mock 无法计算 Facade 上的方法调用

php - 在 Laravel 8 中运行多个 PHPUnit 测试时出错

php - MySQL 使用 sum 获取表

php - PHPUnit 中的测试方法应该如何命名

php - 获取将使用 PHPUNIT 配置文件执行的测试列表