Непонятное поведение при тестировании метода.

Всё про тестирование в Yii 2.0
Ответить
voodooism
Сообщения: 21
Зарегистрирован: 2018.11.12, 10:29

Непонятное поведение при тестировании метода.

Сообщение voodooism » 2018.12.27, 10:30

Имеется модель , наследуемая от класса 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]);
то тест так же удачно отработает.

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

Ответить