테스트를 위한 자동 모의 종속성 주입
injected Trait
사용하면 테스트 목적으로 모든 종속성이 모의된 클래스를 쉽게 만들 수 있습니다.
다음 패턴은 매우 일반적입니다.
A
를 만듭니다.A
의 각 종속성을 조롱하여 예상대로 호출되는지 확인하는 테스트를 만듭니다. 많은 테스트 논리는 결국 객체를 구성하기 위한 상용구가 됩니다. injected Trait
이 상용구를 완전히 제거하여 중요한 것, 즉 테스트 자체에 집중할 수 있도록 하는 것을 목표로 합니다.
최신 릴리스를 얻으려면 composer
사용하십시오(아마도 개발에만 필요할 것입니다).
$ composer require sellerlabs/ injected --dev
우리가 웹 앱을 개발 중이고 사용자가 가입할 때 이메일을 보내고 싶다고 가정해 보겠습니다. 간단한 예를 들어 사용자가 전적으로 이메일 주소로 정의된다고 가정해 보겠습니다. 그들이 가입하면 자연스럽게 감사 이메일을 보내고 싶습니다. 또한 이메일을 실제로 보내지 않고 실제로 이메일이 전송되는지 테스트하고 싶습니다.
먼저 이메일 서비스를 정의해 보겠습니다.
class EmailService
{
public function email ( $ address , $ content )
{
// Send an email to $address with body $content
}
}
(실제 애플리케이션에서는 email
이메일을 발송합니다. 하지만 여기서는 구현에 관심이 없습니다!)
또한 매우 간단한 가입 프로세스를 처리하는 UserController
정의해 보겠습니다.
class UserController
{
private $ service ;
public function __construct ( EmailService $ service )
{
$ this -> service = $ service ;
}
public function signUp ( $ emailAddress )
{
$ this -> service -> email ( $ emailAddress , ' Thanks for signing up! ' );
return $ emailAddress ;
}
}
여기서는 생성자를 통해 EmailService
종속성을 제공하고 이를 (매우 간단한) 가입 프로세스 중에 사용합니다.
이 클래스를 테스트하려면 다음 두 가지 중 하나를 수행해야 합니다.
Mockery
와 같은 것을 사용하여 EmailService
개체를 모의하고 예상 인수로 email
호출되는지 확인하세요. injected Trait
사용하면 옵션 2를 고통 없이 달성할 수 있습니다. 살펴보겠습니다.
use SellerLabs injected injected Trait ;
/**
* Class injected Example
*
* // 1. These are helpful annotations for IDEs and language tools
* @property MockInterface $service
* @method UserController make()
*
* @author Benjamin Kovach <[email protected]>
*/
class injected Example extends PHPUnit_Framework_TestCase
{
// 2. Use our trait
use injected Trait;
// 3. Provide the name of the class to test
protected $ className = UserController::class;
public function testSignUp ()
{
// 4. Make a controller with mocked dependencies
$ controller = $ this -> make ();
$ address = ' [email protected] ' ;
// 5. We can access any mocked dependency of the class as a property
$ this -> service -> shouldReceive ( ' email ' )
-> withArgs (
[
$ address ,
' Thanks for signing up! '
]
);
$ result = $ controller -> signUp ( $ address );
$ this -> assertEquals ( $ address , $ result );
}
}
injected Trait
사용하는 모든 클래스에는 테스트 중인 클래스를 찾는 데 사용되는 $className
속성이 있어야 합니다. injected Trait
이 유형의 객체를 생성하지만 해당 종속성을 모의하고 이를 테스트 클래스 자체에 속성으로 저장하는 단일 공용 메서드 make
를 제공합니다.
따라서 testSignUp
에서는 make()
사용하여 컨트롤러를 구성합니다. 이를 통해 $service
라는 모의 EmailService
유형 개체에 액세스할 수 있습니다. 이는 UserController
의 생성자에서 다음과 같이 정의되었기 때문입니다.
public function __construct ( EmailService $ service )
{
$ this -> service = $ service ;
}
테스트 케이스 기간 동안 $service
멤버 변수는 이 모의 EmailService
에 바인딩되어 컨트롤러의 signUp
메소드가 호출될 때 어떤 일이 발생할지 예측할 수 있습니다. 우리는 조롱 객체를 생성하기 위해 Mockery
사용합니다. 클래스 주석에는 모의 속성이 동적으로 선언되므로 이러한 클래스에 대한 IDE 자동 완성에 도움이 되는 몇 가지 주석이 있습니다.
이 예제는 tests/ injected Example.php
에 있습니다. 마음껏 찔러보세요!
이 특성의 영향은 상대적으로 작아 보일 수 있지만 클래스에 여러 종속성이 있는 대규모 애플리케이션에서 작업할 때 테스트가 훨씬 쉬워집니다.