数据库单元测试绑定到实现细节 [英] Database unit test bound to implementation detail

查看:81
本文介绍了数据库单元测试绑定到实现细节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的PHP类,该类包装了对数据库的访问权以检索用户并希望对其进行单元测试.我目前有以下代码:

I have a simple PHP-Class that wraps the access to the database to retrieve a user and want to unit-test it. I currently have the following code:

要测试的课程:

class UserTable {

    protected $tableGateway;

    public function __construct(\Zend\Db\TableGateway\TableGateway $tableGateway) {
        $this->tableGateway = $tableGateway;
    }

    public function getUserWithId($id) {
        return $this->tableGateway->select(['id' => $id])->current();
    }
}

单元测试:

class UserTableTest extends \PHPUnit_Framework_TestCase {
    public function testGetUserWithIdReturnsCorrectUser() {
        $user = new User();

        $resultSet = new ResultSet();
        $resultSet->initialize([$user]);

        $mockTableGateway = $this->getMock('\Zend\Db\TableGateway\TableGateway', ['select'], [], '', false);
        $mockTableGateway->expects($this->once())->method('select')->with(['id' => 1])->willReturn($resultSet);

        $userTable = new UserTable($mockTableGateway);

        $this->assertEquals($user, $userTable->getUserWithId(1));
    }
}

但是,如果我后来决定更改使用表网关的方式(例如,使用select(['id = ?' => $id]),则单元测试将失败.这会将单元测试绑定到getUserWithId($id)的实现细节,应避免使用.

However, now the unit test would fails if I later decided to change the way I use the table gateway (e.g. use select(['id = ?' => $id]). This binds the unit test to an implementation detail of getUserWithId($id) which should be avoided.

什么是阻止单元测试依赖于实现细节的最佳实践?值得努力建立一个可以运行单元测试的实际测试数据库(这也会大大降低测试的执行速度),还是有一种更好的方法来模拟表网关?

What would be best practice to prevent the unit test from depending on an implementation detail? Is it worth the effort to set up an actual testing database that the unit test can run against (which will also slow down the execution of the test dramatically) or is there a better way to mock the table gateway?

推荐答案

请勿模拟您不拥有的代码!*对于使用数据库的类,您必须编写集成测试.好消息是,这将迫使您将数据库访问与其他逻辑分开.

Do not mock code that you don't own!* For classes that use database, you have to write integration tests. The good things is that this will force you to separate the DB access from other logic.

*这是《成长的面向对象软件,以测试为指导》一书中的实际建议,并以我对使用Doctrine的Entity Manager编写代码的测试的经验为后盾.

*This is actual advice from the "Growing object-oriented software, guided by tests" book, backed up by my own experience with writing tests for code that uses Doctrine's Entity Manager

这篇关于数据库单元测试绑定到实现细节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆