简体   繁体   English

使用PHP-DI注入模拟对象以使用PHPUnit测试控制器

[英]Inject mock objects using PHP-DI for testing controllers with PHPUnit

I have refactored some of my controllers to use dependency injection via property injection as recommended in the "best practices" : 我已经重构了一些控制器, 以按照“最佳实践”中的建议通过属性注入来使用依赖项注入:

final class ZebraController extends Controller
{
    /**
     * @Inject
     * @var AnimalClientInterface
     */
    private $animalsRestClient;

    public function fetchAllZebras(ServerRequestInterface $req): ResponseInterface {
        // ...
    }
}

My PHP-DI configuration is configured to inject an instance of the AnimalClient object for AnimalClientInterface , which is fine in implementation code as there is only 1 real AnimalClient . 我的PHP-DI配置配置为为AnimalClientInterface注入AnimalClient对象的AnimalClientInterface ,这在实现代码中很好,因为只有1个真正的AnimalClient

In my unit test I need to inject a MockZebraClient into this property. 在单元测试中,我需要将MockZebraClient注入此属性。 I cannot simply configure it like I do for the AnimalClient because other classes might be annotated similarly but need, for example, a MockTigerClient for testing. 我不能像对AnimalClient那样简单地对其进行配置,因为其他类可能会被类似地注释,但是需要例如MockTigerClient进行测试。

This is my unit test: 这是我的单元测试:

class ZebraControllerTest extends TestCase
{
    /** @var ZebraController */
    protected $object;

    public function testFetchAllZebras(): void {
        // assertions here
    }
}

I think that using the injectOn method is the correct way to approach this problem but I don't know how to configure the container to choose the correct mock object for the correct test. 我认为使用injectOn方法是解决此问题的正确方法,但我不知道如何配置容器以为正确的测试选择正确的模拟对象。

Constructor injection isn't possible due to the legacy code structure. 由于遗留代码结构,构造函数注入是不可能的。 All the controllers in the application would need to be refactored to use DI in order to change the constructor of Controller . 为了更改Controller的构造函数,需要将应用程序中的所有控制器重构为使用DI。

Maybe there is a PHP-DI specific answer, but I am unfamilar with it. 也许有一个特定于PHP-DI的答案,但是我不熟悉它。 It also seems defining a constructor is not allowed in your case. 在您的情况下,似乎也不允许定义构造函数。 Given that, you can use a static pretend constructor for testing, which allows access to setting internal state: 鉴于此,您可以使用静态的伪装构造函数进行测试,从而允许访问设置内部状态:

<?php
class A {
    private $b;

    public static function construct($b) {
        $a = new A();
        $a->b = $b;
        return $a;
    }
}

class B {

}

$a = A::construct(new B());
var_dump($a);

Returns: 返回值:

object(A)#2 (1) { ["b":"A":private]=> object(B)#1 (0) { } } object(A)#2(1){[“” b“:” A“:private] => object(B)#1(0){}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM