在phpunit文档之后,我提出了以下代码。测试失败,输出显示它没有调用stubbed方法,而是实际方法,命中数据库并从数据库返回数据。我相信我错过了一个步骤,我“注入”测试假人,以便调用它而不是实际的类方法。谁能指出我在这里做错了什么?
我的测试:
$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);
}
感谢十亿!
答案 0 :(得分: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's Eloquent设置测试数据库的所有详细信息。
答案 1 :(得分:0)
将您的模拟实例绑定到类名:
$this->app->instance(CategoryClass::class, $catClassMock);