问题在Laravel 5.3 Project

时间:2016-10-26 15:17:05

标签: laravel phpunit tdd stub

在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);   
}

感谢十亿!

2 个答案:

答案 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);