PHPUnit11でProphecyを使おうと思ったら使えなかったのが事の発端です。
ただし、現在はphpspec/prophecy-phpunitのv2.2.0が出たのでphpunit11でもProphecy使うことが出来ます。
なぜPHPUnit11だとProphecyが使えないのか?
phpspec/phpunit-prophecyはv2.1.0までphpunit11に対応していませんでした。
https://github.com/phpspec/prophecy-phpunit/blob/29f8114c2c319a4308e6b070902211e062efa392/composer.json#L19
composerでprophecy-phpunitをインストールすると以下のようなエラーが発生していました。
1
2
3
4
5
6
7
8
9
10
11
|
$ composer require phpspec/prophecy-phpunit:v2.1.0 -W
./composer.json has been updated/phpunit-test composer require phpspec/prophecy-phpunit:v2.1.0
Running composer update phpspec/prophecy-phpunit --with-all-dependencies
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires phpspec/prophecy-phpunit v2.1.0 -> satisfiable by phpspec/prophecy-phpunit[v2.1.0].
- phpspec/prophecy-phpunit v2.1.0 requires phpunit/phpunit ^9.1 || ^10.1 -> found phpunit/phpunit[9.1.0, ..., 9.6.17, 10.1.0, ..., 10.5.11] but it conflicts with your root composer.json require (^11.0).
|
そもそもphpunitのMockでいいのでは?
Prophecyが使えないので仕方なくphpunitのMockを使ったんですが、ぜんぜん使いやすくてこれでいいやってなりました。
はるか昔phpunitのMockが使いづらくてなんだかんだでProphecy使うようになったのですが、久しぶりにPHPUnitのMock使ったら全然これでいいやってなりました。
phpunitを使ったMockとprophecyを使った比較
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?php
declare(strict_types=1);
namespace Printgraph\PhpSdk\Tests\Client;
use GuzzleHttp\ClientInterface as HttpClientInterface;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Psr\Http\Message\ResponseInterface;
final class ClientTest extends TestCase
{
use ProphecyTrait;
public function testRequestFailure(): void
{
// phpunit標準のmock
$httpClientPhpUnitMock = $this->createMock(HttpClientInterface::class);
$httpClientPhpUnitMock->expects($this->once())
->method('request')
->with('GET', '/v1/test', [])
->willReturn(new Response(500, [], 'error'));
// prophecyのmock
$httpClientProphecyMock = $this->prophesize(HttpClientInterface::class);
$httpClientProphecyMock
->request('GET', '/v1/test', [])
->willReturn(new Response(200, [], 'test'))
->shouldBeCalledOnce();
}
}
|
純粋なspy方式のテストは書けない
phpunit標準のmockでは純粋なspy方式のテストは書くことが出来ません。
メソッドの引数に応じて、コール回数を取るみたいなテストは書けないようです。
メソッドの呼ばれた回数をあとから確認すること程度なら実装は可能です。
1
2
3
4
5
6
7
|
$httpClientPhpUnitMock = $this->createMock(HttpClientInterface::class);
$httpClientPhpUnitMock->expects($spy = $this->any())
->method('request')
->with('GET', '/v1/test', [])
->willReturn(new Response(500, [], 'error'));
self::assertCount(1, $spy->numberOfInvocations());
|
まとめ
- 自分でphpのライブラリを作るならProphecy使わなくてもphpunitのmockで十分
- ただしspy方式のテストが必要な場合はProphecyだったりMockeryだったりリッチなテストライブラリが必要