mingyunyuziyou

单元测试模拟对象-Mock

作者: 秒速五厘米     
 


如果测试A 类,但A类依赖 B 类,B类可能是一个http请求或数据库等操作。我们不希望测试A类时过多考虑B类业务。

但在 A 类的函数代码确实需要 B 类,这时可以使用 mock 机制处理,即我们在A类中使用的B类是假的(模拟出来的)。

使用mock机制的如片:

  • 只专心测试A类

  • 不用为了A类配置数据库或http测试环境

示例如下:

数据库类

class Db
{    
    public function query()
    {        
        return 'houdunren';
    }
}


用户类


class User{
    public function link()
    {        
        return new Db();
    }  
      
    public function get()
        {        
        return $this->link()->query();
    }
}


现在我们看到 User 类依赖 Db类,我们要对User类中的get方法做单元测试,但不想考虑Db类(即不想做数据库连接配置等操作)。


class UserTest extends TestCase
{    
    public function testGet()
    {        
        //创建虚拟Db类
        $db = \Mockery::mock(Db::class);        
        
        //定义虚拟Db的query方法返回值
        $db->allows()->query()->andReturn('这是mock的返回值,不是真正的db返回值');        
        
        //虚拟出User类,并允许调用父类(真正的User类)的方法
        $user = \Mockery::mock(User::class)->makePartial();        
        
        //调用User类的link方法并设置返回值为上面创建的虚拟Db对象
        $user->allows()->link()->andReturn($db);        
        
        //这时操作get方法时使用的Db对象都是虚拟对象
        $this->assertSame('这是mock的返回值,不是真正的db返回值', $res);
    }
}


测试结果


PHPUnit 6.1.0 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 86 ms, Memory: 10.00MB

OK (1 test, 1 assertion)


https://www.houdunren.com/edu/front/topic/27