2012-04-12 135 views
24

我想盡可能使用測試驅動開發 - 這是一種很好的工作方式。我如何測試Symfony2控制器?

Symfony2控制器創建並返回一個新的Response對象,我很困擾。

我想單獨測試一個控制器。

你怎麼做到的?

是否將控制器創建爲Plain Old Object,將其註冊爲服務並使用Dependency Injection將新的Response對象(或Response工廠)傳遞給它?

+2

什麼也正是它返回一個'Response'對象的麻煩? – 2012-04-12 15:59:48

+0

什麼都沒有。我只是不喜歡在控制器中創建一個Response對象的事實。我是依賴注入的堅定信徒,我討厭在除DI容器以外的其他任何東西中看到「新」關鍵字。也許這個信念是錯誤的。 – 2012-04-14 20:44:52

回答

51

通常,您的控制器將不同的對象插在一起,並按正確的順序連接它們。也許他會調用一個存儲庫,讀取一些對象並通過render方法返回它們。也許他會打電話給其他一些做事的經理/經理。

這意味着控制器是高級組件。通常這表明功能測試是按順序而不是單元測試。您不應該試圖通過單元測試獲得100%的代碼覆蓋率。也許你可以這樣想:如果你單元測試控制器調用的所有東西(模型,驗證,表單,存儲庫),會出現什麼問題?大多數情況下,只有在使用生產中涉及的所有實際類時纔會觀察到這一點。

我還想指出,TDD並不意味着每件事都必須經過單元測試。對高級代碼進行一些功能測試是可以的。如上所述,如果您使用單元測試來測試低級別組件,那麼您應該只測試它們如何協同工作,您無法使用mock進行測試,因爲您告訴嘲笑返回值是什麼。

如果您的控制器不僅僅是將系統的某些部分連接在一起,還應該考慮將這些東西重構爲更多可以使用單元測試進行測試的底層類。

所以我的建議將使用功能測試來測試你的控制器和使用單元測試來測試你的模型和你的業務邏輯的東西。

如果你有功能測試掙扎,你可以閱讀以下內容:

+0

好的。我認爲,由於控制器是一個類,它也需要進行單元測試。我不喜歡在編寫測試之前編寫代碼的想法,所以我想知道是否有方法來重構控制器的使用方式,以便能夠對它們進行單元測試。我想在編寫控制器之前,我仍然可以通過編寫功能測試來使用TDD。 – 2012-04-14 20:43:24

2

使用嘲笑孤立的模型,並從主控制器的方法的邏輯其他物體,看到http://www.phpunit.de/manual/3.7/en/test-doubles.html#test-doubles.mock-objects

我認爲,在舊版本,你可以嘲笑整個班級,但最新的PHPUnit 3.6.10,我有它不似乎工作。所以我想你是留下了依賴注入模式

class objss{ 
    function ss(){ 
     $x = new zz(); 
     var_dump($x->z()); 
    } 
} 



class MoTest extends PHPUnit_Framework_TestCase{ 
    public function setUp(){ 

    } 

    public function testA(){ 
     $class = $this->getMock('zzMock', array('z'), array(), 'zz'); 
     $class->expects($this->any())->method('z')->will($this->returnValue('2')); 

     $obj = new objss(); 
     $this->assertEquals('2', $obj->ss()); 
    } 
} 
+0

Totaly - 但這些對象(包括Response對象)將在Controller中實例化。除非我使用DI容器爲控制器提供模型和其他東西。也許我可以創建一個響應工廠服務,並從DI容器中獲取它 - 這樣它(DI容器和工廠)就可以被模擬爲獨立測試Controller類。 – 2012-04-12 15:44:18

0

劉易斯 - 我想我會跳在了這裏。上面的方法讓您在測試中複製更好的動作邏輯部分。這沒什麼錯,許多框架(特別是Rails中的RSPEC)實際上建議您對Controller對象執行單元測試以及功能測試。但是,考慮到你的例子,我想我會跳過單元測試,並採用功能方法。

在我心中,測試的重點是創建一個沙盒環境,運行測試,並檢查副作用和直接結果。如果你認爲你的大部分測試都是孤立了這個方法的話,那麼它可能就是用不同的測試方法或不同的方法來編寫你的課程。考慮到這是一個控制器,並且本質上他們將不同的堆棧粘合在一起,我會在堆棧上創建沙箱。具體而言,我會用這樣的方法:

https://github.com/PolishSymfonyCommunity/SymfonyMockerContainer

我:)

1

單元測試

偉大的工作重構你的控制器是服務: http://symfony.com/doc/current/cookbook/controller/service.html

然後你可以很容易地進行單元測試

功能測試

當然(如已被別人提及的),你可以使用WebTestCase如下所述:http://symfony.com/doc/current/book/testing.html#functional-tests

+0

Symfony並未正式推薦將控制器定義爲服務。它們被一些開發人員用於非常特定的用例,如DDD(域驅動設計)和六角形體系結構應用程序。 – 2017-02-01 13:45:57

+0

誰說的? https://symfony.com/doc/current/controller/service.html 專業人士在他們自己的文檔中超出了控制檯。 我很確定控制器作爲服務將在未來的symfony版本中得到支持,所以我不會過多擔心它是「未正式推薦」。 – 2017-02-07 15:00:07