我正在尝试使用PHPUnit为PHP项目编写单元测试。该项目主要使用SQL数据库。
我使用的任何函数都使用SQL,而且我不知道如何开始编写测试。我在查找要执行的测试时遇到问题,因为它们都使用SQL,并且大多数都没有返回任何内容,只是操纵数据库和会话变量。
这是创建测试的尝试之一:
<?php
require_once '../../test/admin/admin.php';
class checkIsAdminTest extends PHPUnit_Framework_TestCase {
private $ID = '123456789';
private $Class = 0;
private $Pass = 'Aa12345678';
private $First = "Bla";
private $Last = "Bla";
private $Email = "bla@bla.bla";
protected function setUp() {
parent::setUp();
$servername = "localhost";
$username = "root";
$password = "";
$dbname = 'trivia';
$conn = mysqli_connect($servername, $username, $password, $dbname);
$sql = "INSERT INTO `users` (`ID`, `Class`, `Password`, `First`, `Last`, `Email`) VALUES ('" . $this->ID . "', '" . $this->Class . "', '" . sha1($this->Pass) . "', '" . $this->First . "', '" . $this->Last . "', '" . $this->Email . "');";
mysqli_query($conn, $sql);
session_start();
$_SESSION["ID"] = $this->ID;
}
protected function tearDown() {
parent::tearDown();
}
public function __construct() {
}
public function testCheckIsAdmin() {
$this->assertEquals($this->Class == 0 ? False : True, checkIsAdmin());
}
}
?>
该功能检查字段的值是否为#34; Class&#34;名为&#34;用户&#34;的表中的记录是0或1,返回&#34;真&#34;如果它是1,否则为假。
答案 0 :(得分:1)
您遇到的这个问题表明您当前的设计存在更大的问题(“代码味道”),即您有一个类混合了两个问题,即存储(mysql的东西)和业务逻辑本身。这些应该是单独的问题,因此应该是单独的类,你应该考虑如何解决这两个问题(然后你应该使用Dependency Injection将这两个问题结合在一起,方法是将数据库对象传递给业务对象比如构造函数参数)。
一旦你设法将它们分开,你就可以分别对这两个模块进行单元化。对于实现业务逻辑的类,您可以使用mock object替换SQL类,您可以在其中控制被测对象接收的响应,而不必依赖可能具有或可能没有正确数据的真实数据库进行测试。
单元测试的一个重要方面是您必须能够将代码划分为可以尽可能独立测试的不同单元。这需要您比平常更多地考虑应用程序的体系结构。这不仅具有可测试性的优势,还使您的代码更加灵活和适应性更强。例如,如果您决定在数据库和业务对象之间添加缓存层,该怎么办?使用模块化代码,编写一个可以与数据库类相同的方式运行的对象应该相对容易,但是维护自己的内部缓存,如果请求的数据不在缓存中,则只将请求传递给实际的数据库。这应该对客户端类不可见。如果您决定使用Google Cloud中的BigTable替换MySQL,情况也是如此。