phpunit mock을 위한 생성자 인수를 피합니다.

phpunit이 모의 객체에 대해 컨스트럭터를 호출하지 않아도 되는 방법은 무엇입니까?그렇지 않으면 나는 컨스트럭터 인수로 모의 객체가 필요하게 될 것이고, 그것을 위해 다른 객체가 필요하게 될 것이다.API는 다음과 같습니다.

getMock($className, $methods = array(), array $arguments = array(),
$mockClassName = '', $callOriginalConstructor = TRUE,
$callOriginalClone = TRUE, $callAutoload = TRUE) 

작동이 안 돼요.그것은 여전히 건설자의 주장에 대해 불평하고 있다.$callOriginalConstructorfalse로 설정합니다.

생성자에 개체가 하나뿐이고 종속성 주입입니다.그래서 저는 거기에 디자인상의 문제가 없다고 생각합니다.



질문에 대한 답변



사용할 수 있습니다.getMockBuilder뿐만 아니라getMock:

$mock = $this->getMockBuilder('class_name')
->disableOriginalConstructor()
->getMock(); 

자세한 내용은 PHPUnit 설명서의 “테스트 더블 섹션을 참조하십시오.

이렇게 할 수는 있지만, 그렇게 하지 않는 것이 훨씬 좋습니다.코드를 리팩터링하여 (컨스트럭터를 사용하여) 구체적인 클래스를 주입하는 대신 인터페이스에만 의존하도록 할 수 있습니다.즉, 컨스트럭터의 동작을 변경하도록 PHPunit에 지시하지 않고 인터페이스를 모킹 또는 스텁할 수 있습니다.




여기 있습니다.


// Get a Mock Soap Client object to work with.
$classToMock = 'SoapClient';
$methodsToMock = array('__getFunctions');
$mockConstructorParams = array('fake wsdl url', array());
$mockClassName = 'MyMockSoapClient';
$callMockConstructor = false;
$mockSoapClient = $this->getMock($classToMock,



$methodsToMock,



$mockConstructorParams,



$mockClassName,



$callMockConstructor); 



이 질문은 조금 오래된 질문이지만, 처음 방문하시는 분들은createMockmethod(이전의 이름)createTestDoublev5.4.0에서 도입되었습니다).

$mock = $this->createMock($className); 

아래 코드에서 알 수 있듯이PHPUnitFrameworkTestCase클래스(내)phpunit/src/framework/TestCase.php)는 원래 컨스트럭터를 호출하지 않고 기본적으로 모의 객체를 만듭니다.

/** PHPUnitFrameworkTestCase::createMock method */ protected function createMock(string $originalClassName): MockObject {
return $this->getMockBuilder($originalClassName)

->disableOriginalConstructor()

->disableOriginalClone()

->disableArgumentCloning()

->disallowMockingUnknownTypes()

->getMock(); } 



부록으로 첨부하고 싶었습니다.expects()내 조롱의 대상에게 전화를 걸고 나서 건설업자에게 전화한다.PHPUnit 3.7.14에서는 호출 시 반환되는 오브젝트disableOriginalConstructor()말 그대로 객체입니다.

// Use a trick to create a new object of a class // without invoking its constructor. $object = unserialize( sprintf('O:%d:"%s":0:{}', strlen($className), $className) 

안타깝게도 PHP 5.4에는 그들이 사용하지 않는 새로운 옵션이 있습니다.

Reflection Class:: new Instance Without Constructor

사용할 수 없었기 때문에 클래스를 수동으로 반영하고 생성자를 호출해야 했습니다.

$mock = $this->getMockBuilder('class_name')
->disableOriginalConstructor()
->getMock();
$mock->expect($this->once())
->method('functionCallFromConstructor')
->with($this->equalTo('someValue'));
$reflectedClass = new ReflectionClass('class_name'); $constructor = $reflectedClass->getConstructor(); $constructor->invoke($mock); 

주의:functionCallFromConstructprotected, 특히 를 사용해야 합니다.setMethods()따라서 보호된 방법이 조롱당하게 됩니다.예:


$mock->setMethods(array('functionCallFromConstructor')); 

setMethods()먼저 호출해야 합니다.expect()제가 개인적으로 이 체인을 매고 나서disableOriginalConstructor()그 전에getMock().




또는 기본 생성자가 호출되지 않도록 getMock에 매개 변수를 추가할 수도 있습니다.

$mock = $this->getMock(class_name, methods = array(), args = array(),
mockClassName = '', callOriginalConstructor = FALSE); 

그래도 dave1010의 답변이 더 좋은 것 같습니다.완전성을 위해서입니다.