2015-10-30 54 views
1

我想單元測試一個PHP應用程序。 我也是新的單元測試,也許這不應該是我的第一個單元測試用例之一,但我仍然需要做到這一點,所以...如何單元測試一個PHP命令類

我有一個PHP命令2類方法和__construct()。 執行方法遍歷一個數組(通過DBAL讀取獲得)並調用executeSingleRow讀取數據庫時會考慮一些問題,並且只要滿足幾個條件,就會調用另一個命令的execute方法。

我只是無法弄清楚如何一個好的單元測試可以在這裏做,或者我應該如何修改代碼。

這裏是我的類方法:

public function __construct(
    $registry, 
    $firstTableRepository, 
    $secondTableRepository, 
    AnotherCommand $anotherCommand, 
    JobLogRepository $logger = null 
) 
{ 
    $this->registry = $registry; 
    $this->stagione = $this->registry->get('stagione'); 
    $this->firstTableRepository = $firstTableRepository; 
    $this->secondTableRepository = $secondTableRepository; 
    $this->anotherCommand= $anotherCommand; 
    $this->logger = $logger; 
    $this->error = false; 
} 

public function execute($toReplace, $replacer, $selected) 
{ 
    foreach ($selected as $selectedRow) { 
     firstTableID = $selectedRow['ID']; 
     $this->executeSingleRow($toReplace, $replacer, firstTableID); 
    } 
    if ($this->error) { 
     $this->keyException(null, 'Procedura terminata con errori'); 
    } 
} 


public function executeSingleRow($toReplace, $replacer, firstTableID) 
{ 
    if ($toReplace == $replacer) { 
     $this->error = true; 
    } else { 
     $firstTableRow = $this->firstTableRepository->readByID(firstTableID); 
     if (!empty($firstTableRow)) { 
      $CODE = $firstTableRow['CODE']; 
      $newCODE = str_replace($toReplace, $replacer, $CODE); 
      if ($newCODE != $CODE) { 
       $articoloNuovo = $this->secondTableRepository->readByCode($newCODE); 
       if ($articoloNuovo) { 
        $secondTableIDNuovo = $articoloNuovo['secondTableID']; 
        try { 
         $this->anotherCommand->setJobLog($this->jobLog); 
         $this->anotherCommand->execute($secondTableIDNuovo, 'G', firstTableID); 
         return; 
        } catch (\Exception $e) { 
         $this->error = true; 
        } 
       } else { 
        $this->error = true; 
       } 
      } else { 
       $this->error = true; 
      } 
     } else { 
      $this->error = true; 
     } 
    } 
} 

非常感謝這麼樣的閱讀和可能的話回答!

+1

這是非常難以確定這個命令的作用,因此變得很難知道什麼是重要的測試。我想你想確保給定一個對象狀態,執行正確的命令。然而,由於你目前的實施很大程度上依賴於數據庫,你正在嘲笑地獄。我不會試圖單獨測試這個類,它似乎一次嘗試太多東西。 – k0pernikus

+0

有一件事我在我的經驗教訓,如果你想進行單元測試您的應用程序,寫代碼不是之後有一個名爲TDD技術,該技術將迫使你寫鬆耦合類,這將是更容易測試之前做。編寫代碼後編寫測試是一個拖動... –

回答

0

首先,必須有一個類API,它永遠不會在你的包礦工版本改變。因此,假設有一個執行器類具有以下API(建議使用Interface煽動類的)

class CommandExecutor { 
    public function __construct(
    $registry, 
    $firstTableRepository, 
    $secondTableRepository, 
    AnotherCommand $anotherCommand, 
    JobLogRepository $logger = null) {...} 

    public function execute($toReplace, $replacer, $selected){..} 
} 

在第一步驟中(測試設計之後)的模擬對象需要哪些生成測試數據。

class RegistryMock {} 
class TableRepositoryMock{} 
class AnotherCommandMock{} 

模擬類生成固定的數據,所以你知道firstId,secondId是什麼。如果AnotherCommandMock只保存命令,一個簡單的單元測試是:

$registryMock = new RegistryMock(); 
$ftrMock = new TableRepositoryMock($mockData); 
$strMock = new TableRepositoryMock($mockData); 
$aCommand = new AnotherCommandMock(); 
... 
$object = new CommandExecutor($registryMock, $ftrMock, $strMock, $aCommand); 
$object->execute('%Code%', 'TestCode', 'testId1'); 
$aCommand->assertExecute('testId2', 'G', 'testId1'); 

其中$ TESTDATA包含testId1與代碼「代碼:%代碼%」和testId2是代碼「代碼:TestCode」牽強。

正如你可以看到,斷言完全集成到測試數據,模擬對象和業務。