2014-02-13 38 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

当然,总是有道理。感谢你的回答。 –