在 Laravel 5.3 项目中使用 PHPUnit 存根类方法调用的问题
Posted
技术标签:
【中文标题】在 Laravel 5.3 项目中使用 PHPUnit 存根类方法调用的问题【英文标题】:Problems Stubbing class method call using PHPUnit in Laravel 5.3 Project 【发布时间】:2017-03-09 01:02:55 【问题描述】:按照 phpunit 文档,我想出了以下代码。测试失败,输出显示它不是调用存根方法,而是实际方法,访问数据库并从数据库返回数据。我相信我错过了“注入”测试虚拟对象的步骤,以便调用它而不是实际的类方法。谁能指出我在这里做错了什么?
我的测试:
$shouldReturn = '["name":"A Category Name 1","name":"A Category Name 2","name":"A Category Name 3"]';
// Create a mock for the CategoryClass,
$catClassMock = $this->getMockBuilder(CategoryClass::class)->getMock();
// Set up the Test Dummy for the findAll method and stub what should be returned.
$catClassMock->expects($this->once())
->method('findAll')
->with($this->returnValue($shouldReturn));
// Setup the controller object, and call the index method.
$CategoriesController = new CategoriesController();
$returnedResults = $CategoriesController->index();
// Assert the results equal what we told the method to return.
$this->assertEquals($returnedResults, $shouldReturn);
CategoriesController 方法:
public function index()
// List all category
return $this->categoryClass->findAll();
注意:$this->categoryClass 是在 CategoriesController 的构造方法中实例化的。 $this->categoryClass = new CategoryClass;
CategoryClass的findAll方法:
public function findAll()
// List all categories
$categories = Category::all(); // Eloquent call to database.
return json_encode($categories);
感谢十亿!
【问题讨论】:
我想你自己回答了这个问题:“......我错过了一个“注入”测试假人的步骤......” 那么我走对了吗?文档中没有任何额外的步骤,这只是我对问题的分析。如果我确实需要“注入”这个存根,我该怎么做呢?这是我正在使用的文档:phpunit.de/manual/current/en/… 【参考方案1】:当您在模拟类对象中模拟一个方法时,您必须使用该模拟类对象来获取您的模拟方法的响应。
所以,如果你想让 CategoriesController->index() 方法调用你模拟的 Categories 类而不是真正的 Categories 类,你必须将 Categories 类注入到 CategoriesController 类中。像这样的东西应该可以工作:
$shouldReturn = '["name":"A Category Name 1","name":"A Category Name 2","name":"A Category Name 3"]';
$catClassMock = $this->getMockBuilder(CategoryClass::class)
->setMethods(['findAll'])
->getMock();
// Set up the Test Dummy for the findAll method and stub what should be returned.
$catClassMock
->method('findAll')
->willReturn($shouldReturn);
// Setup the controller object, and call the index method.
$CategoriesController = new CategoriesController();
$CategoriesController->categoryClass = $catClassMock;
$returnedResults = $CategoriesController->index();
// Assert the results equal what we told the method to return.
$this->assertEquals($returnedResults, $shouldReturn);
我还应该提到,创建一个在每次测试之前播种的内存中 sqlite 数据库也可以工作,并且无需模拟 Eloquent 查询。从长远来看,它也可能更容易维护。查看https://laracasts.com/series/phpunit-testing-in-laravel 了解有关如何为 Laravel 的 Eloquent 设置测试数据库的所有详细信息。
【讨论】:
【参考方案2】:将你的模拟实例绑定到类名:
$this->app->instance(CategoryClass::class, $catClassMock);
【讨论】:
感谢您的回复,我期待这样的事情。不幸的是,它对我不起作用。我仍然得到返回的实际数据库数据,而不是预期的 $shouldReturn。 你可以试试更新的线吗?我认为bind
不是正确的方法。
再次感谢,非常感谢您的帮助!尽管如此,它仍然无法正常工作并返回整个数据库输出。以上是关于在 Laravel 5.3 项目中使用 PHPUnit 存根类方法调用的问题的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 5.3 NotFoundHttpException
在 Laravel 5.3 Passport 中添加 Access-Control-Allow-Origin 标头响应