이 패키지는 내부 PHP 기능을 최대한 간단하게 모의하는 데 도움이 됩니다. time()
, str_contains()
, rand
등과 같은 모의 함수가 필요할 때 이 패키지를 사용하세요.
설치
용법
런타임 모의
사전 정의된 모의
이전 두 가지 방법을 혼합
PHPUnit 9
PHPUnit 10 이상
PHPUnit 확장 등록
모의 등록
상태
통화 추적
전역 네임스페이스 함수
내부 기능 구현
내부 기능
제한
데이터 제공자
작곡가는 xepozz/internal-mocker --dev가 필요합니다.
주요 아이디어는 매우 간단합니다. PHPUnit용 리스너를 등록하고 먼저 Mocker 확장을 호출하는 것입니다.
새로운 파일을 생성합니다 tests/MockerExtension.php
생성된 파일에 다음 코드를 붙여넣습니다.
<?phpdeclare(strict_types=1);namespace AppTests;use PHPUnitRunnerBeforeTestHook;use PHPUnitRunnerBeforeFirstTestHook;use XepozzInternalMockerMocker;use XepozzInternalMockerMockerState;final class MockerExtension은 BeforeTestHook, BeforeFirstTestHook을 구현합니다. {공용 함수 실행BeforeFirstTest(): void{$mocks = [];$mocker = new Mocker();$mocker->load($mocks); MockerState::saveState(); }공개 함수 실행BeforeTest(string $test): void{ MockerState::resetState(); } }
phpunit.xml.dist
에 후크를 확장자로 등록합니다.
<확장자> <확장 클래스="AppTestsMockerExtension"/> </확장자>
새로운 파일을 생성합니다 tests/MockerExtension.php
생성된 파일에 다음 코드를 붙여넣습니다.
<?phpdeclare(strict_types=1);namespace AppTests;사용 PHPUnitEventTestPreparationStarted;사용 PHPUnitEventTestPreparationStartedSubscriber;사용 PHPUnitEventTestSuiteStarted;사용 PHPUnitEventTestSuiteStartedSubscriber;사용 PHPUnitRunnerExtensionExtension;사용 PHPUnitRunnerExtensionFacade;사용 PHPUnitRunnerExtensionParameterCollection;사용 PHPUnitTextUIConfigurationConfiguration;XepozzInternalMockerMocker 사용;XepozzInternalMockerMockerState 사용;최종 클래스 MockerExtension이 확장 기능을 구현합니다. {공용 함수 부트스트랩(구성 $configuration, Facade $facade, ParameterCollection $parameters): void{$facade->registerSubscribers(새 클래스()는 StartedSubscriber를 구현합니다. {공용 함수 알림(시작된 $event): void{ MockerExtension::load(); } }, 새로운 클래스는 PreparationStartedSubscriber {public function inform(PreparationStarted $event): void{를 구현합니다. MockerState::resetState(); } }, ); }공용 정적 함수 로드(): void{$mocks = [];$mocker = new Mocker();$mocker->load($mocks); MockerState::saveState(); } }
phpunit.xml.dist
에 후크를 확장자로 등록합니다.
<확장자> <bootstrap class="AppTestsMockerExtension"/> </확장자>
여기에는 ./vendor/bin/phpunit
실행할 때마다 호출되는 확장 기능이 등록되어 있습니다.
기본적으로 모든 함수는 /vendor/bin/xepozz/internal-mocker/data/mocks.php
파일에 생성되어 저장됩니다.
경로를 변경하려면 Mocker
생성자의 첫 번째 인수를 재정의하세요.
$mocker = new Mocker('/path/to/your/mocks.php');
패키지는 함수를 모의하는 몇 가지 방법을 지원합니다.
런타임 모의
사전 정의된 모의
이전 두 가지 방법을 혼합
모의 함수와 함께 사용할 테스트 케이스를 만들고 싶다면 먼저 등록해야 합니다.
생성된 MockerExtension::executeBeforeFirstTest
로 돌아가서 $mocks
변수를 편집합니다.
$모의 = [ ['네임스페이스' => 'AppService','이름' => '시간', ], ];
이 모의는 생성된 래퍼를 통해 AppService
네임스페이스 아래의 모든 time()
호출을 프록시합니다.
테스트에서 결과를 모의하려면 필요한 테스트 케이스에 다음 코드를 작성해야 합니다.
MockerState::addCondition( 'AppService', // 네임스페이스 '시간', // 함수 이름 [], // 인수 100 // 결과);
콜백을 사용하여 함수 결과를 설정할 수도 있습니다.
MockerState::addCondition( '', // 네임스페이스 'headers_sent', // 함수 이름 [null, null], // 두 인수는 모두 참조이며 함수 호출 시 아직 초기화되지 않았습니다. fn (&$file, &$line) => $file = $line = 123, // 콜백 결과);
따라서 테스트 케이스는 다음과 같습니다.
<?phpnamespace AppTests;AppService 사용;PHPUnitFrameworkTestCase 사용;ServiceTest 클래스는 TestCase를 확장합니다. {공용 함수 testRun2(): void{$service = new Service(); MockerState::addCondition('AppService','시간', [],100);$this->assertEquals(100, $service->doSomething()); } }
XepozzInternalMockerTestsIntegrationDateTimeTest::testRun2
에서 전체 예제를 확인하세요.
사전 정의된 모의를 사용하면 전역적으로 동작을 모의할 수 있습니다.
이는 전체 프로젝트에 대해 모의하려는 경우 각 테스트 케이스에 MockerState::addCondition(...)
작성할 필요가 없음을 의미합니다.
서로 다른 네임스페이스의 동일한 함수가
Mocker
에서는 동일하지 않다는 점을 명심하세요.
따라서 생성된 MockerExtension::executeBeforeFirstTest
로 돌아가서 $mocks
변수를 편집합니다.
$모의 = [ ['네임스페이스' => 'AppService','name' => '시간','결과' => 150,'인수' => [], ], ];
이 변형 이후에는 각 AppServicetime()
150
반환합니다.
많은 모의를 추가할 수 있습니다. Mocker
arguments
값을 호출 함수의 인수와 비교하고 필요한 결과를 반환합니다.
혼합이란 처음에는 사전 정의된 모의를 사용하고 나중에는 런타임 모의를 사용할 수 있음을 의미합니다.
Runtime mock
사용하는 경우 기능을 모의한 후에도 다른 테스트 케이스에서 여전히 모의가 발생하는 문제에 직면할 수 있습니다.
MockerState::saveState()
및 MockerState::resetState()
이 문제를 해결합니다.
이러한 메서드는 "현재" 상태를 저장하고 적용된 각 Runtime mock
모의를 언로드합니다.
Mocker->load($mocks)
후에 MockerState::saveState()
사용하면 사전 정의된 모의 항목만 저장됩니다.
MockerState::getTraces()
메소드를 사용하여 모의 함수 호출을 추적할 수 있습니다.
$traces = MockerState::getTraces('AppService', 'time');
$traces
다음 구조의 배열 배열이 포함됩니다.
[ ['arguments' => [], //'trace' 함수의 인수 => [], // debug_backtrace 함수의 결과'result' => 1708764835, // 함수의 결과],// ... ]
모든 내부 기능은 원본 기능과 호환되도록 스텁 처리되었습니다. 이는 함수가 원본과 마찬가지로 참조된 인수( &$file
)를 사용하도록 만듭니다.
src/stubs.php
파일에 있습니다.
새 함수 시그니처를 추가해야 하는 경우 Mocker
생성자의 두 번째 인수를 재정의하세요.
$mocker = new Mocker(stubPath: '/path/to/your/stubs.php');
전역 함수를 모의하는 방법은 php.ini
에서 비활성화하는 것입니다: https://www.php.net/manual/en/ini.core.php#ini.disable-functions
가장 좋은 방법은 추가 플래그와 함께 명령을 실행하여 테스트용으로만 비활성화하는 것입니다.
php -ddisable_functions=${함수} ./vendor/bin/phpunit
PHPStorm을 사용하는 경우
Run/Debug Configurations
섹션에서 명령을 설정할 수 있습니다.Interpreter options
필드에-ddisable_functions=${functions}
플래그를 추가합니다.
scripts
섹션 아래의composer.json
파일에 명령을 보관할 수 있습니다.
{ "스크립트": {"테스트": "php -ddisable_functions=time,serialize,header,date ./vendor/bin/phpunit" } }
${functions}
모의하려는 함수 목록(쉼표로 구분)으로 바꿉니다(예:time,rand
).
이제 전역 함수도 모의할 수 있습니다.
php.ini
에서 함수를 비활성화하면 더 이상 해당 함수를 호출할 수 없습니다. 즉, 직접 구현해야 합니다.
분명히 PHP로 구현된 거의 모든 함수는 Bash 함수와 동일해 보입니다.
함수를 구현하는 가장 짧은 방법은 `bash command`
구문을 사용하는 것입니다:
$mocks[] = [ '네임스페이스' => '', '이름' => '시간', '함수' => fn () => `날짜 +%s`, ];
구현하지 않고 전역 함수를 두면 함수 호출이 발생하여 치명적인 오류가 발생한다는 점을 명심하세요.
때로는 namespace
강제로 사용하지 않고 모의된 함수가 모의되지 않는 경우 불쾌한 상황에 직면할 수 있습니다.
function
. @dataProvider
에서 PHP 인터프리터 파일을 만들려고 한다는 의미일 수 있습니다. 이에 주의하세요. 해결 방법으로 테스트 생성자에서 모커를 호출하는 것이 좋습니다. 따라서 먼저 확장 메서드인 executeBeforeFirstTest
의 모든 코드를 새로운 정적 메서드로 이동하고 이를 executeBeforeFirstTest
및 __construct
메서드 모두에서 호출하세요.
최종 클래스 MyTest는 PHPUnitFrameworkTestCase를 확장합니다. {공용 함수 __construct(?string $name = null, 배열 $data = [], $dataName = '') {AppTestsMockerExtension::load();parent::__construct($name, $data, $dataName); } /// ...}
최종 클래스 MockerExtension은 BeforeTestHook, BeforeFirstTestHook을 구현합니다. {공용 함수 실행BeforeFirstTest(): void{self::load(); }공용 정적 함수 로드(): void{$mocks = [];$mocker = new Mocker();$mocker->load($mocks); MockerState::saveState(); }공개 함수 실행BeforeTest(string $test): void{ MockerState::resetState(); } }
이는 모두 PHPUnit 9.5 이하의 이벤트 관리 시스템 때문입니다. 데이터 공급자 기능은 이벤트가 발생하기 전에 작동하기 시작하므로 런타임 시작 시 함수를 모의하는 것은 불가능합니다.