簡體   English   中英

模擬/存根在 PHPUnit 中實現數組訪問的類的對象

[英]Mocking/Stubbing an Object of a class that implements arrayaccess in PHPUnit

這是我正在為其編寫測試套件的類的構造函數(它擴展了 mysqli):

function __construct(Config $c)
{
    // store config file
    $this->config = $c;

    // do mysqli constructor
    parent::__construct(
        $this->config['db_host'],
        $this->config['db_user'],
        $this->config['db_pass'],
        $this->config['db_dbname']
    );
}

傳遞給構造函數的Config類實現了 php 內置的arrayaccess接口:

class Config implements arrayaccess{...}

如何模擬/存根Config對象? 我應該使用哪個,為什么?

提前致謝!

如果您可以輕松地從數組創建Config實例,那將是我的偏好。 雖然您希望在可行的情況下單獨測試您的單元,但簡單的合作者(例如Config應該足夠安全以用於測試。 設置它的代碼可能比等效的模擬對象更易於閱讀和編寫(不易出錯)。

$configValues = array(
    'db_host' => '...',
    'db_user' => '...',
    'db_pass' => '...',
    'db_dbname' => '...',
);
$config = new Config($configValues);

話雖如此,您可以像模擬任何其他對象一樣模擬實現ArrayAccess對象。

$config = $this->getMock('Config', array('offsetGet'));
$config->expects($this->any())
       ->method('offsetGet')
       ->will($this->returnCallback(
           function ($key) use ($configValues) {
               return $configValues[$key];
           }
       );

您還可以使用at強加特定的訪問順序,但這樣會使測試變得非常脆弱。

提出問題后 8 年,首次回答后 5 年,我遇到了同樣的問題並得出了類似的結論。 這就是我所做的,這與 David 接受的答案的第二部分基本相同,除了我使用的是更高版本的 PHPUnit。

基本上你可以模擬ArrayAccess接口方法。 只需要記住,您可能想要模擬offsetGetoffsetExists (您應該始終在使用之前檢查數組鍵是否存在,否則您可能會在代碼中遇到E_NOTICE錯誤和不可預測的行為,如果它不存在)。



$thingyWithArrayAccess = $this->createMock(ThingyWithArrayAccess::class);

$thingyWithArrayAccess->method('offsetGet')
     ->with('your-offset-here')
     ->willReturn('test-value-1');

$thingyWithArrayAccess->method('offsetExists')
     ->with($'your-offset-here')
     ->willReturn(true);

當然,您可以在測試中使用真正的數組,例如


$theArray = [
    'your-offset-here-1' => 'your-mock-value-for-offset-1',
];

$thingyWithArrayAccess = $this->createMock(ThingyWithArrayAccess::class);

$thingyWithArrayAccess->method('offsetGet')
     ->willReturnCallback(
          function ($offset) use ($theArray) {
              return $theArray[$offset];
          }
     );

$thingyWithArrayAccess->method('offsetExists')
     ->willReturnCallback(
          function ($offset) use ($theArray) {
              return array_key_exists($offset, $theArray);
          }
     );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM