首頁  >  文章  >  後端開發  >  PHP 單元測試實務中的常見問題與解決方案

PHP 單元測試實務中的常見問題與解決方案

PHPz
PHPz原創
2024-05-06 12:42:011192瀏覽

PHP 單元測試的常見問題:外部相依性測試: 使用模擬框架(如 Mockery)建立假的依賴項並斷言其交互作用。私有成員測試: 使用反射 API(如 ReflectionMethod)存取私有成員或使用測試可見性修飾符(如 @protected)。資料庫互動測試: 使用資料庫測試框架(如 DbUnit)設定和驗證資料庫狀態。外部 API/Web 服務測試: 使用 HTTP 用戶機庫模擬交互,在測試環境中使用本機或存根伺服器。

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

PHP 單元測試中的常見問題

問題1:如何針對具有外部相依性的程式碼進行單元測試?

解決方案: 使用模擬框架,如 PHPUnit 的 Mockery 或 Prophecy,允許你建立假的依賴項對象,並對其互動進行斷言。

use Prophecy\Prophet;

class UserRepoTest extends \PHPUnit\Framework\TestCase
{
    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 \PHPUnit\Framework\TestCase
{
    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 PHPUnit\DbUnit\TestCase;

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 GuzzleHttp\Client;

class UserServiceTest extends \PHPUnit\Framework\TestCase
{
    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 單元測試實務中的常見問題與解決方案的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn