摘要:可是我們在做單元測試的時候,希望盡可能少的產(chǎn)生依賴。后記任何一個可靠的系統(tǒng),單元測試都是必不可少的。慶幸的是,幫我們提供了好用的單元測試。
本文是我在實踐后的一點總結(jié),難免有不妥之處。如有幸得大神路過,還望不吝賜教,小弟在此謝過了!
很早就知道有單元測試的概念,也曾嘗試過,但是一直對單元測試的概念和方法,比較模糊。在聽了 @vimac 大神的講堂 PHP單元測試與測試驅(qū)動開發(fā) 后,慢慢地對單元測試和 PHPUnit 的認(rèn)識清晰了起來,也開始慢慢地去實踐單元測試。
Laravel 中的依賴我們都知道,Laravel 使用了 IoC,各個模塊之間也因此解耦了。而正是因為這一點,我們在 Laravel 中編寫單元測試的時候,變得更加輕松了。
舉個栗子考慮以下場景。我們在開發(fā)中,可能會在控制器和模型之間加一個 Repository 來處理數(shù)據(jù)。那么我們的 Controller 就會依賴 Respository。利用 Laravel 的 IoC,我們可以定義一個 Service Provider 來集中將 Respository 注入到容器中。
假設(shè)我們現(xiàn)在有這樣一個 Repository,里面記錄了商品的信息,我們想要在 Controller 中獲取某件商品信息,然后執(zhí)行一些業(yè)務(wù)邏輯。
Class GoodRepository { public function getGoodById($goodId) { // TODO: Get good by its id. } } class GoodController extends Controller { public function show($id, GoodRepository $goodRepository) { // TODO: Do something with good info from that repository. } } // In route/api.php Route::get("/api/good/{id}", "GoodController@show"); // Create a RepositoriesServiceProvider in Provider/RepositoriesServiceProvider.php。 // And inject the GoodRepository into Container. class RepositoriesServiceProvider extends ServiceProvider { public function boot() { } public function register() { $this->app->singleton(GoodRepository::class); } }
好了,我們可以發(fā)現(xiàn),GoodController 是依賴 GoodRepository 的,而 GoodRepository 是依賴數(shù)據(jù)庫中的數(shù)據(jù)的。可是我們在做單元測試的時候,希望盡可能少的產(chǎn)生依賴。所以,我們應(yīng)該希望能夠掌控 GoodRepository 所返回的數(shù)據(jù)。
在 Laravel,提供了 $this->get("/path/to/route"); 的方法來對 HTTP 請求進(jìn)行測試。這個測試必然會涉及到剛才所提到的那些依賴,如何解決這個依賴的問題,我們可以請出我們的主角————樁件。
樁件將對象替換為(可選地)返回配置好的返回值的測試替身的實踐方法稱為上樁(stubbing)。
這是 PHPUnit 文檔上 的解釋。那我的理解呢,所謂的樁件,就是模擬一個依賴的類的行為,使得這個行為所做的事情在我們自己的掌控之中。比如上面的這種情況,我們希望模擬 GoodRepository 的 getGoodById 方法返回與真正的返回結(jié)構(gòu)相同的值,而不需要依賴外部數(shù)據(jù)源。
在 Laravel 中使用樁件我們通過 Service Provider 注冊了 GoodRepository 單例,那么按照這個思路,我們在寫單元測試的時候,就可以將我們定義的樁件,注冊為 GoodRepository 單例。
class GoodControllerTest extends TestCase { public function testShow() { $data = []; // The data returns from GoodRepository::getGoodById. $stub = $this->createMock(GoodRepository::class); $stub->method("getGoodById")->will($this->returnValue($data)); $this->app->singleton(GoodRepository::class, function () use ($stub) { return $stub; }); $response = $this->get("/api/good/1"); // Some assertions. } }
我們通過在這里將樁件 $stub 用單例模式注冊給了 Container,在調(diào)用 $this->get("/api/good/1"); 時原本在 Controller 中的 GoodRepository 依賴就變成了我們自定義的樁件 $stub。我們將 $data 定義為和返回值相同的結(jié)構(gòu),注冊到樁件中。這樣,所有的數(shù)據(jù)都在我們可控的范圍了。
如果我們在這里不使用樁件,而是直接依賴外部(數(shù)據(jù)庫)中的數(shù)據(jù),那么如果 id 為 1 的數(shù)據(jù)被刪除了,我們是不是就要改成 2 了呢?我們是不是就要重新計算數(shù)據(jù)了匹配斷言了呢?這樣的測試,可靠性便大大降低。
后記任何一個可靠的系統(tǒng),單元測試都是必不可少的。慶幸的是,PHPUnit 幫我們提供了好用的單元測試。本文所講的,也只是 PHPUnit 的九牛一毛。而我自己也在慢慢摸索慢慢實踐中。與君共勉。
最后還是推薦去聽一下 @vimac 的講堂 PHP單元測試與測試驅(qū)動開發(fā),受益匪淺。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/25620.html
摘要:前言首先歡迎關(guān)注我的博客在前面幾個博客中,我詳細(xì)講了容器各個功能的使用綁定的源碼解析的源碼,今天這篇博客會詳細(xì)介紹容器的一些細(xì)節(jié),一些特性,以便更好地掌握容器的功能。 前言 首先歡迎關(guān)注我的博客: www.leoyang90.cn 在前面幾個博客中,我詳細(xì)講了 Ioc 容器各個功能的使用、綁定的源碼、解析的源碼,今天這篇博客會詳細(xì)介紹 Ioc 容器的一些細(xì)節(jié),一些特性,以便更好地掌握容...
摘要:一旦你完成了相應(yīng)函數(shù),只需要把注解刪去,就可以進(jìn)行正常的測試。表示該方法只執(zhí)行一次,并且在所有方法之后執(zhí)行。 測試類型 單元測試(Unit test) 單元測試關(guān)注單一的類. 它們存在的目的是檢查這個類中的代碼是否按照期望正確運行. 集成測試(Integration test) 顧名思義, 集成測試是檢查開發(fā)的模塊和其他模塊整合時是否正常工作.雖然集成測試的代碼影響范圍比單元測試要廣,...
摘要:基本上,測試金字塔描述你應(yīng)該編寫單元測試集成測試和端到端測試。集成測試要比端到端測試多,單元測試甚至要更多一些。應(yīng)用程序單元測試編寫單元測試,是為了看看給定的模塊單元是否工作。 本文轉(zhuǎn)載自:眾成翻譯譯者:網(wǎng)絡(luò)埋伏紀(jì)事鏈接:http://www.zcfy.cc/article/1754原文:https://blog.risingstack.com/node-hero-node-js-un...
摘要:譯者按從標(biāo)準(zhǔn),語法以及模塊角度來看,的發(fā)展讓人目不暇接,那么面試題也得與時俱進(jìn)。因此,手動檢查所有依賴是不現(xiàn)實的。為,加之后返回。自從年雙十一正式上線,累計處理了億錯誤事件,得到了金山軟件百姓網(wǎng)等眾多知名用戶的認(rèn)可。 譯者按: 從ECMAScript標(biāo)準(zhǔn),Node.js語法以及NPM模塊角度來看,Node.js的發(fā)展讓人目不暇接,那么面試題也得與時俱進(jìn)。 原文: Node.js In...
閱讀 1340·2021-09-22 15:09
閱讀 2669·2021-08-20 09:38
閱讀 2408·2021-08-03 14:03
閱讀 874·2019-08-30 15:55
閱讀 3376·2019-08-30 12:59
閱讀 3556·2019-08-26 13:48
閱讀 1892·2019-08-26 11:40
閱讀 673·2019-08-26 10:30