phpUnit – 如何測試類別中的保護或私有方法
通常在 phpUnit 中, 為了避免過度設計,要測試的方法都是 Class 的公開方法。但有時候我們要對受保護的方法或私有方法、甚至是屬性作測試,那該如何測試寫?
我們可以藉由 「ReflectionClass 反射類別 / ReflectionMethod 反射方法」 來達到,以下是 phpUnit 運行在路徑 tests/ 底下的範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
<?php namespace Tests; use PHPUnit\Framework\TestCase; // 受測範例 class User { protected static function getPhone($name) { return "{$name}: 09123456789"; } private function search($id, $name) { return "{$id} - {$name}"; } } // 測試 User 類別 class MyTest extends TestCase { // 測試靜態保護的方法 public function testProtectedStaticMethod() { // 直接反射方法 $reflectionMethod = new \ReflectionMethod(User::class, 'getPhone'); $reflectionMethod->setAccessible(true); // 代入該方法的參數 $result = $reflectionMethod->invoke(new User(), "Cary"); $this->assertEquals("Cary: 09123456789", $result); } // 測試私有方法 public function testPrivateMethod() { // 直接反射方法 $reflectionMethod = new \ReflectionMethod(User::class, 'search'); $reflectionMethod->setAccessible(true); // 代入該方法的參數 $result = $reflectionMethod->invoke(new User(), "500800", "Cary"); $this->assertEquals("500800 - Cary", $result); } // 混和測試 public function testMix() { // 只反射類別 $reflectionClass = new \ReflectionClass(User::class); // 從反射的類別下去取得靜態方法 $method = $reflectionClass->getMethod('getPhone'); $method->setAccessible(true); // 為該方法帶入參數 $invoke = $method->invoke(new User(), 'Cary'); // 從反射的類別下去取得方法 $method = $reflectionClass->getMethod('search'); $method->setAccessible(true); // 為該方法帶入參數 $invoke = $method->invoke(new User(), '500800', 'Cary'); } } |
至於何時用 ReflectionClass 或 ReflectionMethod,如果要同時測試 Class 底下多個 Methods,那麼使用 ReflectionClass 會方便一點;如果只是單純測試某個 Methods 那麼就使用 ReflectionMethod 。