卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章52735本站已运行3120

PHP 单元测试实践中的常见问题与解决方案

php 单元测试的常见问题:外部依赖项测试: 使用模拟框架(如 mockery)创建假的依赖项并断言其交互。私有成员测试: 使用反射 api(如 reflectionmethod)访问私有成员或使用测试可见性修饰符(如 @protected)。数据库交互测试: 使用数据库测试框架(如 dbunit)设置和验证数据库状态。外部 api/web 服务测试: 使用 http 客户机库模拟交互,在测试环境中使用本地或存根服务器。

PHP 单元测试实践中的常见问题与解决方案

PHP 单元测试中的常见问题

问题 1:如何针对带有外部依赖项的代码进行单元测试?

解决方案: 使用模拟框架,如 PHPUnit 的 Mockery 或 Prophecy,允许你创建假的依赖项对象,并对其交互进行断言。

use ProphecyProphet;

class UserRepoTest extends PHPUnitFrameworkTestCase
{
    public function testFetchUser(): void
    {
        $prophet = new Prophet();
        $cache = $prophet->prophesize(Cache::class);

        $userRepo = new UserRepo($cache->reveal());

        $actualUser = $userRepo->fetchUser(1);

        $cache->get(1)->shouldHaveBeenCalled();
        $this->assertEquals($expectedUser, $actualUser);
    }
}

问题 2:如何测试私有方法或属性?

解决方案: 使用反射 API(例如 ReflectionClassReflectionMethod),允许你访问私有成员。然而,它可能会使测试难以维护。

另一种解决方案是使用测试特定的可见性修饰符,例如 PHPUnit 的 @protected

class UserTest extends PHPUnitFrameworkTestCase
{
    public function testPasswordIsSet(): void
    {
        $user = new User();

        $reflector = new ReflectionClass($user);
        $property = $reflector->getProperty('password');

        $property->setAccessible(true);
        $property->setValue($user, 'secret');

        $this->assertEquals('secret', $user->getPassword());
    }
}

问题 3:如何测试数据库交互?

解决方案: 使用数据库测试框架,如 PHPUnit 的 DbUnit 或 Doctrine DBAL Assertions,允许你设置和验证数据库状态。

use PHPUnitDbUnitTestCase;

class PostRepoTest extends TestCase
{
    protected function getConnection(): Connection
    {
        return $this->createDefaultDBConnection();
    }

    public function testCreatePost(): void
    {
        $dataset = $this->createXMLDataSet(__DIR__ . '/initial-dataset.xml');
        $this->getDatabaseTester()->setDataSet($dataset);
        $this->getDatabaseTester()->onSetUp();

        $post = new Post(['title' => 'My First Post']);
        $postRepo->persist($post);
        $postRepo->flush();

        $this->assertTrue($this->getConnection()->getRowCount('posts') === 1);
    }
}

问题 4:如何测试依赖外部 API 或 Web服务的代码?

解决方案: 使用 HTTP 客户机库来模拟与外部服务的交互。在测试环境中,你可以使用本地或存根服务器。

use GuzzleHttpClient;

class UserServiceTest extends PHPUnitFrameworkTestCase
{
    public function testFetchUser(): void
    {
        $httpClient = new Client();
        $userService = new UserService($httpClient);

        $httpClient
            ->shouldReceive('get')
            ->with('/users/1')
            ->andReturn(new Response(200, [], json_encode(['id' => 1, 'name' => 'John Doe'])));

        $user = $userService->fetchUser(1);

        $this->assertInstanceOf(User::class, $user);
        $this->assertEquals(1, $user->getId());
    }
}
卓越飞翔博客
上一篇: PHP 代码复用性与可扩展性增强
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏