PHP 單元測試的常見問題:外部相依性測試: 使用模擬框架(如 Mockery)建立假的依賴項並斷言其交互作用。私有成員測試: 使用反射 API(如 ReflectionMethod)存取私有成員或使用測試可見性修飾符(如 @protected)。資料庫互動測試: 使用資料庫測試框架(如 DbUnit)設定和驗證資料庫狀態。外部 API/Web 服務測試: 使用 HTTP 用戶機庫模擬交互,在測試環境中使用本機或存根伺服器。
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(例如 ReflectionClass
和 ReflectionMethod
),允許你存取私有成員。然而,它可能會使測試難以維護。
另一種解決方案是使用測試特定的可見性修飾符,例如 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中文網其他相關文章!