全局狀態(tài)

2018-02-24 15:41 更新

全局狀態(tài)

使用單件(singleton)的代碼很難測試。使用全局變量的代碼也一樣。通常情況下,欲測代碼和全局變量之間會(huì)強(qiáng)烈耦合,并且其創(chuàng)建無法控制。另外一個(gè)問題是,一個(gè)測試對全局變量的改變可能會(huì)破壞另外一個(gè)測試。

在 PHP 中,全局變量是這樣運(yùn)作的:

  • 全局變量 $foo = 'bar'; 實(shí)際上是存儲(chǔ)為 $GLOBALS['foo'] = 'bar'; 的。

  • $GLOBALS這個(gè)變量是一種被稱為超全局變量的變量。

  • 超全局變量是一種在任何變量作用域中都總是可用的內(nèi)建變量。

  • 在函數(shù)或者方法的變量作用域中,要訪問全局變量 $foo,可以直接訪問 $GLOBALS['foo'],或者用 global $foo; 來創(chuàng)建一個(gè)引用全局變量的局部變量。

除了全局變量,類的靜態(tài)屬性也是一種全局狀態(tài)。

默認(rèn)情況下,PHPUnit 用一種更改全局變量與超全局變量($GLOBALS、$_ENV$_POST、$_GET$_COOKIE、$_SERVER$_FILES、$_REQUEST)不會(huì)影響到其他測試的方式來運(yùn)行所有測試。同時(shí),還可以選擇將這種隔離擴(kuò)展到類的靜態(tài)屬性。

Note

對全局變量和類的靜態(tài)屬性的備份與還原操作使用了 serialize()unserialize()

某些類的實(shí)例對象(比如 PDO)無法序列化,因此如果把這樣一個(gè)對象存放在比如說 $GLOBALS 數(shù)組內(nèi)時(shí),備份操作就會(huì)出問題。

the section called “@backupGlobals”中所討論的 @backupGlobals 標(biāo)注可以用來控制對全局變量的備份與還原操作。另外,還可以提供一個(gè)全局變量的黑名單,黑名單中的全局變量將被排除于備份與還原操作之外,就像這樣:

class MyTest extends PHPUnit_Framework_TestCase
{
    protected $backupGlobalsBlacklist = array('globalVariable');

    // ...
}

Note

在方法(例如 setUp() 方法)內(nèi)對 $backupGlobalsBlacklist 屬性進(jìn)行設(shè)置是無效的。

the section called “@backupStaticAttributes” 中提到的 @backupStaticAttributes 標(biāo)注可以用于在每個(gè)測試之前備份所有已聲明類的靜態(tài)屬性值并在其后恢復(fù)。

它所處理的并不只是測試類自身,而是在測試開始時(shí)已聲明的所有類。它只作用于靜態(tài)類屬性,不作用于函數(shù)內(nèi)聲明的靜態(tài)變量。

Note

只有啟用了 @backupStaticAttributes 的測試方法才會(huì)在方法之前執(zhí)行此操作。如果在此之前運(yùn)行的某個(gè)沒有啟用 @backupStaticAttributes 的測試方法改變了靜態(tài)屬性的值,那么被備份及還原的將會(huì)是這個(gè)改變后的值——而非初始聲明時(shí)提供的默認(rèn)值。PHP 并不額外記錄任何靜態(tài)變量的聲明時(shí)提供的初始默認(rèn)值。

同樣的情況也發(fā)生于測試內(nèi)部新加載/聲明的類的靜態(tài)屬性上。它們也無法在測試結(jié)束之后復(fù)原為聲明時(shí)提供的原始默認(rèn)值,因?yàn)闊o從得知這些默認(rèn)值。這些被修改過的值會(huì)泄漏到后繼測試中。

對單元測試而言,推薦在 setUp() 中顯式的重置測試中使用到的靜態(tài)屬性(最好同時(shí)在 tearDown() 中執(zhí)行重置,這樣就保證不會(huì)影響到后繼的測試)。

可以提供黑名單來將靜態(tài)屬性從備份與還原操作中排除出去:


class MyTest extends PHPUnit_Framework_TestCase
{
    protected $backupStaticAttributesBlacklist = array(
      'className' => array('attributeName')
    );

    // ...
}

Note

在方法(例如 setUp() )內(nèi)對 $backupStaticAttributesBlacklist 屬性進(jìn)行設(shè)置是無效的。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號