我正在为我的存储库编写测试,并且我有一个page()方法,它接受一个PaginationQuery对象,该对象由特定模型的限制,方向和游标组成,并返回一个json paginator对象,我正在努力进行模拟,这是我的代码:
我的存储库代码:
public function page(PaginationQuery $pagination)
{
$paginator = new Paginator($this->model);
return $paginator->paginate($pagination->limit(), $pagination->direction(), $pagination->cursor());
}
我的测试:
public function test_paging_with_mocking()
{
// seed articles
$seededArticles = [
new Article(['title' => 'Article 1']),
new Article(['title' => 'Article 2']),
new Article(['title' => 'Article 3']),
new Article(['title' => 'Article 4']),
new Article(['title' => 'Article 5']),
new Article(['title' => 'Article 6']),
];
foreach ($seededArticles as $seededArticle) {
$seededArticle->save();
}
$limit = PaginationQuery::defaultLimit();
$direction = PaginationQuery::defaultDirection();
$cursor = PaginationQuery::defaultCursor();
$pagination = new PaginationQuery($limit, $direction, $cursor);
$mPaginator = M::mock(Paginator::class);
$mPaginator->shouldReceive('paginate')->with($limit, $direction, $cursor)->andReturn([]);
$receivedResult = $this->repo->page($pagination);
}
我需要在这里做几件事:
在模拟paginator时测试page()方法,因为我不关心输出,我只需要声明限制,方向和游标值正确传递给paginate ()方法。
我还需要在page()方法中注入paginator类,因为模拟类的new
实例会在模拟这个类时导致错误
在测试的这一行$mPaginator->shouldReceive('paginate')->with($limit, $direction, $cursor)->andReturn([]);
我需要添加一次()但是这样做时我收到以下错误:
正好1次,但被称为0次
答案 0 :(得分:1)
我认为这里的问题是在page
方法中使用以下方法创建新对象:
$paginator = new Paginator($this->model);
而不是以某种方式将其传递给存储库。
这导致从不使用Paginator的mock,因为创建了新对象。
您可以快速验证这一点,如果您paginate
Paginator
方法返回testtesttest
并在测试结束时添加:
$this->assertEquals([], $receivedResult);
您将看到收到的结果将是testtesttest
而不是[]
,尽管您使用andReturn([])
进行设置,因为您不会将模拟对象传递到存储库。
使测试通过的最简单的解决方案是将page
方法更改为:
public function page(PaginationQuery $pagination, Paginator $paginator)
{
return $paginator->paginate($pagination->limit(), $pagination->direction(), $pagination->cursor());
}
现在整个测试结束如下:
$mPaginator->shouldReceive('paginate')->once()->with($limit, $direction, $cursor)->andReturn([]);
$receivedResult = $this->repo->page($pagination, $mPaginator);
$this->assertEquals([], $receivedResult);
将通过,因为您将模拟对象传递到存储库,现在如您所见,即使在[]
模型中返回Paginator
testtest
修改强>
在评论中,您询问了如何注入Paginator对象,因此可能有解决方案。
重写您的存储库以使用如下代码:
public function page(PaginationQuery $pagination)
{
$paginator = $this->getPaginator();
return $paginator->paginate($pagination->limit(),
$pagination->direction(), $pagination->cursor());
}
protected function getPaginator()
{
return new Paginator($this->model);
}
所以你现在正在创建额外的方法来创建paginator实例。
现在让我们回到你的考试。
在测试构造函数中的某处,您创建了存储库实例。让我们假设您这样做:
$this->repo = new \App\Repositories\ArticleRepository();
现在,我们希望将其更改为部分模拟:
$this->repo = M::mock("\\App\\Repositories\\ArticleRepository[getPaginator]")->shouldAllowMockingProtectedMethods();
所以我们告诉我们将为getPaginator
方法创建模拟,我们使用shouldAllowMockingProtectedMethods
因为我们不想模拟受保护的方法(getPaginator
是受保护的方法)而且它不能默认情况下完成。
现在,最后一行测试应如下所示:
$mPaginator->shouldReceive('paginate')->once()->with($limit, $direction, $cursor)->andReturn([]);
// here we mock getPaginator method to return our mock $mPaginator
$this->repo->shouldReceive('getPaginator')->once()->andReturn($mPaginator);
$receivedResult = $this->repo->page($pagination);
$this->assertEquals([], $receivedResult);
所以当你看到我们现在达到了我们想要的效果时,我们不必在运行page
方法时传递Paginator对象。