[英]phpunit with mockery - how to test a mocked object is constructed with proper arguments
[英]Laravel unable to test job with mocked Service and object. The Mockery spy fails to detect called method
我想測試我的工作的功能:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use App\Model\Model;
use App\Services\Service;
class MyJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
/**
* Undocumented variable
*
* @var User
*/
private $model;
public function __construct(Model $model)
{
$this->model=$model;
}
public function handle(Service $service): void
{
if($this->model->shouldCallService){
$service->method();
}
}
}
我想用純單元測試來測試它:
namespace Tests\Jobs;
use Tests\TestCase;
use Mockery;
use App\Services\MyService;
use App\Jobs\MyJob;
use App\Model\MyModel;
class TestJob extends TestCase
{
public function testMethod()
{
$this->app->instance(MyModel::class,\Mockery::mock(MyModel::class,function($mock){
$mock->shouldReceive('save')->andReturn(true);
}));
$model=factory(MyModel::class)->create([
'shouldCallService'=>true,
]);
$mockedNewsLetterService=Mockery::spy(MyService::class);
$mockedNewsLetterService->shouldReceive('method')->once();
$job=new MyJob($model);
$job->handle($mockedNewsLetterService);
$mockedNewsLetterService->shouldHaveReceived()->method()->with($model);
}
public function tearDown() {
parent::tearDown();
Mockery::close();
}
}
但是一旦我通過以下方式測試它:
./vendor/bin/phpunit ./test/Jobs/TestJob.php
我得到以下輸出:
PHPUnit 7.5.20 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 46.12 seconds, Memory: 34.00 MB
There was 1 error:
1) Tests\Jobs\TestJob::testMethod
Mockery\Exception\InvalidCountException: Method method(<Any Arguments>) from Mockery_1_App_Services_MyService should be called
at least 1 times but called 0 times.
/var/www/html/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php:47
/var/www/html/vendor/mockery/mockery/library/Mockery/Expectation.php:312
/var/www/html/vendor/mockery/mockery/library/Mockery/ReceivedMethodCalls.php:46
/var/www/html/vendor/mockery/mockery/library/Mockery/VerificationDirector.php:36
/var/www/html/vendor/mockery/mockery/library/Mockery/VerificationDirector.php:104
/var/www/html/vendor/mockery/mockery/library/Mockery/VerificationDirector.php:46
/var/www/html/vendor/mockery/mockery/library/Mockery/HigherOrderMessage.php:47
/var/www/html/tests/Jobs/TestJob.php:32
ERRORS!
Tests: 1, Assertions: 3, Errors: 1.
你知道為什么spy沒有檢測到method
方法的調用嗎?
你錯誤地調用了shouldHaveReceived
的嘲弄。
使用這種方法:
$mockedNewsLetterService->shouldHaveReceived(`method`)->with($model);
另外,為了測試作業調度,我使用了app
的bindMethod
,因此測試應該是:
public function testMethod()
{
$this->app->instance(MyModel::class,\Mockery::mock(MyModel::class,function($mock){
$mock->shouldReceive('save')->andReturn(true);
}));
$model=factory(MyModel::class)->create([
'shouldCallService'=>true,
]);
$mockedNewsLetterService=Mockery::spy(MyService::class);
$this->app->bindMethod(NewsLetterSubscribeUserJob::class.'@handle', function ($job, $app) use ($mockedNewsLetterService){
return $job->handle($mockedNewsLetterService);
});
MyJob::dispatchNow($model);
$mockedNewsLetterService->shouldHaveReceived('method')->with($model);
}
如您所見,我使用該應用程序來處理作業調度。 同樣為了在測試期間避免 3rd 方服務,我也使用dispatchNow
以免我的工作排隊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.