我需要测试一个存储库,它有一个通过构造函数注入的Eloquent模型。
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);
}
}
对此有何想法?
答案 0 :(得分:4)
我认为您的主要问题是您没有正确使用存储库模式。您应该将构造函数中传递的模型视为原型。这不是一件真实的事情,而是你用于其他事情的一个例子。在存储库中,您可能有一个方法getUnpaidOrders,它将执行return $this->model->wherePaid('0')->get();
之类的操作。正如您所看到的,我们不是将实例作为一个实际的具体实例进行交互,而是为了实现更广泛的范围。
在您的计算方法中,您实际上是在此原型模型上设置值。我不知道你打算用这些做什么,但据我所知,这不是存储库模式应该做的。存储库上的方法通常是类似静态的方法,您可以在其中调用它们(可能带有一些输入)并返回一些东西。它们不应对任何类型的内部状态产生影响,因为存储库不应具有任何内部状态。
希望这是有道理的。