为什么在运行 API 测试时 Symfony DI 容器会增加服务的实例?

问题描述

我有一个应该只有一个实例的服务,我确信 DI 容器会处理它。当我通过邮递员发送请求时,一切正常,容器总是返回相同的实例。我什至添加一个额外的字段,其中包含在对象创建过程中生成的用于调试的随机数。

class ReadModel
{
    private ?Database $database;

    // Temporary field for debugging purpose
    private int $tmp;

    public function __construct()
    {
        $this->database = null;

        $this->tmp = rand(1,1000);
    }

    public function setDatabase(Database $database): void
    {
        $this->database = $database;

        dump($this->tmp); // returns e.g. 836 when codeception test is run
    }

    public function getCollection(string $collectionName): Collection
    {
        dump($this->tmp); // returns e.g. 390 when codeception test is run

        return $this->database->selectCollection($collectionName);
    }
}

当 Postman(开发环境)发送请求时,dump() 函数返回的两个数字是相等的(同一个实例被注入到其他使用它的服务中)。但是当我运行 Codeception 测试时,此服务的行为有所不同。当我在一项服务中调用 setDatabase()ReadModel 方法并在另一项服务中调用 getCollection 方法时,我收到 $tmp 字段的两个不同值。这意味着 ReadModel 服务的两个不同实例已注入到我的服务中。在两种环境(开发和测试)中如何实现相同的行为?

ReadModel 服务是自动装配的,因此我不会粘贴 services.yaml 内容

我的技术栈:Symfony 5.1,Codeception 4.1

附注。通过 Codeception 测试,我指的是像这样的 end2end API 测试,而不是单元测试:

<?PHP

use Codeception\Util\HttpCode;

class CreateProductCest
{
    public function _before(ApiTester $I)
    {
        // Authentication stuff...
    }

    public function shouldCreateProductWithNoException(ApiTester $I)
    {
        $data = [
            'name' => 'test123',];

        $I->sendPost('/product/create',$data);

        $I->seeResponseIsJson();
        $I->seeResponseCodeIs(HttpCode::OK);
        $I->seeResponseContainsJson([]);
    }
}

ReadModel 对象的方法调用示例。大部分代码都被剪掉了,我只留下了相关部分的代码

class JwtDecodedListener
{
    private ReadModel $readModel;

    public function __construct(
        ReadModel $readModel
    ) {
        $this->readModel = $readModel;
    }

    public function onJWTDecoded(JWTDecodedEvent $event)
    {
        // some code
        $client = new Client("mongodb://{$mongoDbUser}:{$mongoDbPass}@{$this->mongoHost}/{$mongoDb}");
        $this->readModel->setDatabase($client->selectDatabase($mongoDbUser));
    }
}
class ProductProjection
{
    private ReadModel $readModel;

    public function __construct(
        ReadModel $readModel
    ) {
        $this->readModel = $readModel;
    }

    public function whenProductWasCreated(Product $product): void
    {
        // $collectionName is from a factory
        $collection = $this->readModel->getCollection($collectionName);
    }
}

编辑:正如评论中所建议的,我在 dump() 类的构造函数添加ReadModel 调用,我的结论是相同的。从邮递员执行的发布请求 - 一个构造函数校准。 Codeception 执行相同的请求 - 2 次构造函数调用。还是不知道是什么原因。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...