[英]Laravel 7 partial mock eloquent model fails with __construct(), but no expectations were specified
我正在使用 Laravel 7 并尝试部分模拟 eloquent model ..
我的 controller 注入了 eloquent model 依赖项:
use App\Models\Ticket;
class TicketsController extends Controller
{
/** @var Ticket */
private $tickets;
public function __construct(Ticket $ticket) {
$this->tickets = $ticket;
}
public function get() {
$tickets = $this->tickets::whereNull('staff_id')
->where('status', '!=', $this->tickets::STATUS_CLOSED)
->orderBy('created_at', 'desc')
->get();
}
}
单元测试:
use App\Models\Ticket;
$this->partialMock(Ticket::class, function($mock) {
$mock->shouldReceive('get')
->once()
->andReturn([]);
});
$response = $this->json('get', route('tickets'));
$response->assertOk();
失败:
testing.ERROR:收到 Mockery_0_App_Models_Ticket::__construct(),但未指定预期 {"exception":"[object] (Mockery\Exception\BadMethodCallException(code: 0): Received Mockery_0_App_Models_Ticket::__construct(),但没有预期在 /opt/project/vendor/mockery/mockery/library/Mockery/Loader/EvalLoader.php(34) 指定:eval()'d code:911)
还尝试为此更改测试:
$ticketsMock = Mockery::mock(Ticket::class);
$ticketsMock
->makePartial()
->shouldReceive('get')
->once()
->andReturn([]);
$this->instance(Ticket::class, $ticketsMock);
但得到完全相同的错误..
如果我将模拟替换为非部分模拟并伪造 model 上的所有方法调用,它工作正常。但是一些 eloquent 查询会很长,我试图通过部分模拟完成它,所以我不必伪造每个单链调用,例如->shouldReceive('something')->andReturnSelf()
partial 的问题在于whereNull
返回的是QueryBuilder
而不是 Ticket model。
我认为一个好的解决方案是 mocking demeter 链。 您可以通过在字符串whereNull->where->orderBy->get
中进行表达来模拟流畅的调用。 我得到了以下示例以在本地工作。
$this->mock(Ticket::class, function($mock) {
$mock->shouldReceive('whereNull->where->orderBy->get')
->once()
->andReturn([]);
});
您仍然必须表达模拟调用的路径,但我认为这是非常合理和直接的,因为您不必考虑参数和返回。
我稍微更改了 controller 方法,因为您在对象上静态调用了方法。 为了确保它正常工作,我的 controller 逻辑是这样的。
$tickets = $this->tickets->whereNull('staff_id')
->where('status', '!=', Ticket::STATUS_CLOSED)
->orderBy('created_at', 'desc')
->get();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.