PHP 单元测试:使用 PHPUnit 保障代码质量

分类:后端开发 时间:2026-02-24 浏览:1
1

一、单元测试的价值

  • 提前发现 BUG:在开发阶段发现问题,而非上线后;

  • 方便重构:修改代码后,运行测试用例即可验证功能是否正常;

  • 减少联调成本:每个函数 / 方法都经过测试,联调时问题更少;

  • 文档作用:测试用例可作为代码的使用示例。

二、PHPUnit 环境搭建

  1. 安装 Composer(PHP 包管理工具):

php - r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php - r "unlink('composer-setup.php');"
mv composer.phar /usr/local/bin/composer
  1. 创建项目并安装 PHPUnit:

mkdir phpunit-demo && cd phpunit-demo
composer require --dev phpunit/phpunit ^9.0
  1. 创建phpunit.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
         colors="true"
         verbose="true">
    <testsuites>
        <testsuite name="Unit Tests">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

三、PHPUnit 基础用法

1. 编写测试用例

创建src/Calculator.php(待测试的类):

<?php
namespace App;

class Calculator
{
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }

    public function subtract(int $a, int $b): int
    {
        return $a - $b;
    }

    public function multiply(int $a, int $b): int
    {
        return $a * $b;
    }

    public function divide(int $a, int $b): float
    {
        if ($b == 0) {
            throw new \InvalidArgumentException("除数不能为0");
        }
        return $a / $b;
    }
}
?>

创建tests/CalculatorTest.php(测试类):

<?php
namespace Tests;

use App\Calculator;
use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    /**
     * 测试加法
     */
    public function testAdd()
    {
        $calculator = new Calculator();
        $this->assertEquals(5, $calculator->add(2, 3)); // 断言:2+3=5
        $this->assertEquals(0, $calculator->add(-1, 1));
    }

    /**
     * 测试减法
     */
    public function testSubtract()
    {
        $calculator = new Calculator();
        $this->assertEquals(1, $calculator->subtract(3, 2));
        $this->assertEquals(-5, $calculator->subtract(2, 7));
    }

    /**
     * 测试乘法
     */
    public function testMultiply()
    {
        $calculator = new Calculator();
        $this->assertEquals(6, $calculator->multiply(2, 3));
        $this->assertEquals(0, $calculator->multiply(0, 5));
    }

    /**
     * 测试除法
     */
    public function testDivide()
    {
        $calculator = new Calculator();
        $this->assertEquals(2, $calculator->divide(6, 3));
        $this->assertEquals(1.5, $calculator->divide(3, 2));

        // 断言抛出异常
        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage("除数不能为0");
        $calculator->divide(5, 0);
    }
}
?>
2. 运行测试
./vendor/bin/phpunit

输出示例:

PHPUnit 9.6.10 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.4.33
Configuration: /var/www/phpunit-demo/phpunit.xml

....                                                                4 / 4 (100%)

Time: 00:00.005, Memory: 6.00 MB

OK (4 tests, 7 assertions)

四、实战:测试业务逻辑

测试UserService中的密码加密方法:

<?php
namespace Tests;

use App\Services\UserService;
use PHPUnit\Framework\TestCase;
use Illuminate\Hashing\BcryptHasher;

class UserServiceTest extends TestCase
{
    protected $userService;

    // 每个测试方法执行前初始化
    protected function setUp(): void
    {
        $this->userService = new UserService();
    }

    /**
     * 测试密码加密
     */
    public function testPasswordHash()
    {
        $password = '123456';
        $hash = $this->userService->hashPassword($password);
        
        // 断言加密后的密码不等于原密码
        $this->assertNotEquals($password, $hash);
        // 断言密码验证通过
        $hasher = new BcryptHasher();
        $this->assertTrue($hasher->check($password, $hash));
    }
}
?>

五、进阶:Mock 模拟依赖

当测试的方法依赖数据库 / 第三方接口时,使用 Mock 模拟依赖,避免测试受外部影响:

<?php
public function testUserRegister()
{
    // 创建Mock对象
    $userModelMock = $this->createMock(\App\Models\User::class);
    // 模拟exists()方法返回false
    $userModelMock->method('exists')->willReturn(false);
    // 模拟create()方法返回用户对象
    $userModelMock->method('create')->willReturn((object)[
        'id' => 1,
        'username' => 'test',
        'email' => 'test@demo.com'
    ]);

    $userService = new UserService($userModelMock);
    $user = $userService->register([
        'username' => 'test',
        'email' => 'test@demo.com',
        'password' => '123456'
    ]);

    $this->assertEquals(1, $user->id);
    $this->assertEquals('test', $user->username);
}
?>
 
文章链接:http://www.qwkf.cn//houduan/28.html
文章标题:PHP 单元测试:使用 PHPUnit 保障代码质量

相关阅读