我想测试在触发eloquent event时是否调用方法。
在下面的示例中,当学生实例保存到学生实例时,我想通过 isApproved()方法自动设置已批准的属性数据库。
以下是学生模型类:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
public $guarded = [];
protected static function boot()
{
parent::boot();
// set approved attribute if its value is NULL
self::creating(function (self $student) {
$student->approved = $student->approved ?? $student->isApproved();
});
}
/**
* @return bool
*/
public function isApproved()
{
return ($this->age >= 14) && ($this->age <= 20);
}
}
为实现这一点,我在学生类的创建事件上添加了一个回调函数。
我正在尝试使用以下测试来测试 isApproved()方法调用:
<?php
namespace Tests\Feature;
use App\Student;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class StudentTest extends TestCase
{
use DatabaseMigrations;
/**
* @test
*/
public function student_is_auto_approved_on_save()
{
$mock = \Mockery::mock(Student::class);
$mock->shouldReceive('isApproved')->once();
Student::create([
'name' => 'John Doe',
'age' => 14
]);
}
}
但测试未通过,显示以下转储
PHPUnit 5.7.21 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 246 ms, Memory: 16.00MB
There was 1 error:
1) Tests\Feature\StudentTest::student_is_auto_approved_on_save
Mockery\Exception\InvalidCountException: Method isApproved() from Mockery_0_App_Student should be called
exactly 1 times but called 0 times.
/students/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php:37
/students/vendor/mockery/mockery/library/Mockery/Expectation.php:298
/students/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php:120
/students/vendor/mockery/mockery/library/Mockery/Container.php:297
/students/vendor/mockery/mockery/library/Mockery/Container.php:282
/students/vendor/mockery/mockery/library/Mockery.php:152
/students/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:144
/home/user/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:186
/home/user/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:116
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
我做错了什么?
答案 0 :(得分:0)
尝试
<?php
namespace Tests\Feature;
use App\Student;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class StudentTest extends TestCase
{
use DatabaseMigrations;
/**
* @test
* @dataProvider providerAutoApprovedAge
*
* @param int $age
*/
public function student_is_auto_approved_on_save($age)
{
$student = Student::create([
'name' => 'John Doe' . $age,
'age' => $age,
]);
$student->save();
$this->assertTrue($student->approved);
}
public function providerAutoApprovedAge()
{
for ($age = 14; $age <= 20; $age++) {
yield [
$age,
];
}
}
/**
* @test
* @dataProvider providerNotAutoApprovedAge
*
* @param int $age
*/
public function student_is_not_auto_approved_on_save($age)
{
$student = Student::create([
'name' => 'John Doe' . $age,
'age' => $age,
]);
$student->save();
$this->assertFalse($student->approved);
}
public function providerNotAutoApprovedAge()
{
for ($age = 0; $age < 14; $age++) {
yield [
$age,
];
}
for ($age = 21; $age < 120; $age++) {
yield [
$age,
];
}
}
}
你可能想断言学生是
您可以使用数据提供程序。
或者,你可以这样删除方法:
class StudentStub extends Student
{
public $hasApprovedBeenInvoked = false;
public function isApproved()
{
$this->hasApprovedBeenInvoked = true;
}
}
class StudentTest extends TestCase
{
use DatabaseMigrations;
/**
* @test
*/
public function student_is_auto_approved_on_save($age)
{
$student = StudentStub::create([
'name' => 'John Doe' . $age,
'age' => $age,
]);
$student->save();
$this->assertTrue($student->hasApprovedBeenInvoked);
}
}
但是,这仅在Student::create()
使用后期静态绑定并返回StutentStub
的实例时才有效。
而且大多数情况下,你不想嘲笑被测系统,但是如果你有任何合作者的话。在这里,没有任何。
供参考,见