UploadedFile - Codeception
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 |
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 it finally fixed? I'm having the same error :(
@marcis14 no, it was not. Do you have time to contribute a fix?
Yes. If you explain me how to do it, please.
I think https://github.com/yiisoft/yii2/issues/14260#issuecomment-401725014 is still valid but tests were moved to https://github.com/Codeception/module-yii2
Sorry, didn't get it.
In case it helps, this was my solution:
// Copy if TESTING, move if not $this->file->saveAs($fullPath, !YII_ENV_TEST);