@romajke

Почему происходит такое странное поведение при тестировании Codeception?

Приложение написано на Yii2. Имеется модель наследуемая от класса yii\base\Model, которая содержит в себе несколько AR моделей.Ниже привожу код модели.

class InquiryForm extends \yii\base\Model
{
    /**
     * @var ActiveRecord Адрес регистрации клиента
     */
    public $regAddress;

    /**
     * @var ActiveRecord Анкета
     */
    public $inquiry;

    /**
     * @inheritdoc
     */
    public function load($data, $formName = null)
    {
        $load = [
            'inquiry' => $this->inquiry,
            'regAddress' => $this->regAddress,
        ];
        $success = false;

        foreach ($load as $name => $form) {
            $success = $form->load($data, $formName !== '' ? null : $name);
        }
        return $success;
    }
}


Я пытаюсь протестировать метод модели load c помощью codeception.

Привожу код тестов:
Для начала в методе before() отсоединяю модель AR от взаимодействия с базой, "мОкая" методы "save" & "attributes" следующим образом:
protected function _before()
    {
        $this->_address = $this->createFormMock(Address::class,
            [
                'field1',
                'field2',
                'field3',
                'field4',
                'field5',
                'field6'
            ]
        );

        $this->_inquiry = $this->createFormMock(InquiryLogical::class,
            [
                'field1',
                'field2',
                'field3',
                'field4',
                'field5',
                'field6'
            ]
        );
    }

    protected function createFormMock(string $class, array $attributes)
    {
        $mockObject = $this->getMockBuilder($class)
            ->setMethods(['save', 'attributes'])
            ->getMock();
        $mockObject->method('save')->willReturn(true);
        $mockObject->method('attributes')->willReturn($attributes);

        return $mockObject;
    }


И наконец, пытаюсь протестировать метод:
public function testLoadForm()
    {
        $data = [
            'there is some data from $_POST'
        ];

        $form = new InquiryForm(['inquiry' => $this->_inquiry, 'regAddress' => $this->_address]);

        $this->assertTrue($form->load($data));
    }


Первое время я очень долго не мог понять, почему мой простейший тест никак не отрабатывает и всё время выдает ошибку Failed asserting that false is true. Сначала думал, что как то некорректно создан mockObject или некорректные данные в массиве $data, но нет,
там всё было правильно( при загрузке этих же данных на страничке всё корректно отрабатывает).
Спустя некоторое время была обнаружена следующая интересная зависимость:

Если в тестируемом методе порядок загружаемых методов следующий:
$load = [
            'inquiry' => $this->inquiry,
            'regAddress' => $this->regAddress,
        ];

а в тесте я создаю объект формы вот таким образом:
$form = new InquiryForm(['inquiry' => $this->_inquiry, 'regAddress' => new Address()]);


то тест отрабатывает.

И наоборот, если в методе изменить порядок:
$load = [
            'regAddress' => $this->regAddress,
            'inquiry' => $this->inquiry,
        ];

а в тесте создавать объект формы следующим образом
$form = new InquiryForm(['inquiry' => new Inquiry(), 'regAddress' => $this->_address]);

то тест так же удачно отработает.

Это подтвержтает то, что мОки и тестовые данные созданы правильно. Но я не могу понять, почему так происходит? Буду рад любой помощи.
  • Вопрос задан
  • 48 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы