2014-02-13 39 views
0

我需要測試一個存儲庫,它有一個通過構造函數注入的Eloquent模型。Laravel - Testing Repositories

class EloquentOrderRepository implements OrderRepositoryInterface 
{ 

    protected $model; 

    public function __construct(Order $model) 
    { 
     $this->model = $model; 
    } 

    public function calculateValues(array $deliveryOption = null) 
    { 
     if (! is_null($deliveryOption)) { 
      $this->model->value_delivery = (float) number_format($deliveryOption['price'], 2); 
     } 

     $this->model->value_products = (float) number_format($this->model->products->getTotal(), 2); 
     $this->model->value_total = (float) $this->model->value_products + $this->model->value_delivery; 
    } 
} 

我的問題是當我打電話$this->model->value_products(或任何屬性)。 Eloquent模型嘗試調用setAttribute方法,該方法在模擬模型中不存在。如果我嘲笑這種方法,我無法正確設置屬性,我的測試斷言將失敗。

這裏是我的測試:

<?php 
class EloquentOrderRepositoryTest extends \PHPUnit_Framework_TestCase 
{ 

    protected $model, $repository; 

    public function setUp() 
    { 
     $this->model = Mockery::mock('Order'); 
    } 

    public function test_calculate_values() 
    { 
     $repository = new EloquentOrderRepository($this->model); 

     $this->model->products = m::mock('SomeCollection'); 
     $this->model->products->shouldReceive('getTotal')->once()->withNoArgs()->andReturn(25); 

     $this->model->calculateValues(array('price' => 12)); 
     $this->assertEquals(12, $this->model->value_delivery); 
     $this->assertEquals(25, $this->model->value_products); 
     $this->assertEquals(37, $this->model->value_total); 
    } 
} 

對這個有什麼想法?

回答

4

我認爲你的主要問題是你沒有正確使用存儲庫模式。您應該將構造函數中傳遞的模型作爲原型來考慮。這不是一件真正的事情,而是你用於其他事情的事例。在存儲庫中,您可能會有一個方法getUnpaidOrders,它將執行類似return $this->model->wherePaid('0')->get();的操作。正如您所看到的,我們不是將實例與實際交互作爲實際的具體實例,而是更多地實現更廣泛的範圍。

在您的計算方法中,您實際上是在此原型模型上設置值。我不知道你打算怎麼做,但據我所知,這不是存儲庫模式應該做的。存儲庫中的方法通常是類似於靜態的方法,您可以在其中調用它們(可能有一些輸入)並返回。它們不應該對任何類型的內部狀態產生影響,因爲存儲庫不應該具有任何類型的內部狀態。

希望這是有道理的。

+0

當然,總是有道理。感謝你的回答。 –