Yii2: UploadedFile - Codeception

Created on 6 Jun 2017  路  11Comments  路  Source: yiisoft/yii2

What steps will reproduce the problem?

When i have a codeception test, i send the next POST request

$files = [
'file_name' => codecept_data_dir('image.jpg')
];

but it gets conflicted with the function UploadedFile::saveAs ()

[...] elseif (is_uploaded_file($this->tempName)) [...]

Because the file is not upladed but 'emulated' via codeception

What is the expected result?

File Uploaded

What do you get instead?

File is not uploaded

Additional info

| Q | A
| ---------------- | ---
| Yii version | 2.0.12
| PHP version | 7.0.18
| Operating system | Linux Ubuntu 16.04

Codeception ready for adoption bug

All 11 comments

Please fix this issue, we can not write any test cases around uploading a file at the moment.

The same problem here. Can't test because any use of attachFile() will not really save the file in Yii2 at all because UploadedFile::saveAs() with $deleteTempFile = false will check is_uploaded_file() and, if it has not POSTed, it will not be saved. (not sure move_uploaded_file() would work too for the sake of the 'cli' mode.)

Any idea on how to fix it?

Yeah, @samdark. I tryed this and it works fine in my tests (files are being 'copied' or moved as expected):

public function saveAs($file, $deleteTempFile = true)
    {
        if ($this->error == UPLOAD_ERR_OK) {
            // added this if block
            if (YII_ENV_TEST) {
                if ($deleteTempFile) {
                    return rename($this->tempName, $file);
                } else {
                    return copy($this->tempName, $file);
                }
            }
            if ($deleteTempFile) {
                return move_uploaded_file($this->tempName, $file);
            } elseif (is_uploaded_file($this->tempName)) {
                return copy($this->tempName, $file);
            }
        }

        return false;
    }

Can't we mock UploadedFile somehow instead of mixing production code and tests?

About the mock, maybe somebody has some idea but now I just cant see how since UploadedFile is being directly instantiated inside the SUT code without use SL/DI.

@SamMousa do you have any ideas about that?

We could mock the function; since UploadedFile is in a namespace, doing this will make it work:

namespace \yii\web {
    function is_uploaded_file() {
        return true;
    }

This code could then be part of the yii2 module, this is a working example:


<?php

namespace test\abc;

class Test {


    public function override() {

        eval(<<<PHP
        namespace test\abc {
            function is_uploaded_file() {
                echo "OVERRIDE IN EFFECT\n";
                return true;
            }
        }
PHP
        );
    }
}

$test = new Test();
$file = tempnam(sys_get_temp_dir(), 'x');
file_put_contents($file, 'abc');
var_dump(is_uploaded_file($file));
$test->override();
var_dump(is_uploaded_file($file));

Sounds much better than conditions in UploadedFile itself. Should we move it to Codeception repo issues?

Yes, first there should be a failing test case created: https://github.com/codeception/yii2-tests
@BerkantC are you up for that?
Basically you create a new app config with a test that fails.

In your case you could even just add a test here:
https://github.com/Codeception/yii2-tests/tree/master/cases/simple/functional

Everytime I enter in github I learn more! It seems a very good solution @SamMousa.

Was this page helpful?
0 / 5 - 0 ratings