5

I'm trying to write tests for an endpoint that expects a post request with an attached CSV file. I know to simulate the post request like this:

$this->post('/foo/bar');

But I can't figure out how to add the file data. I tried manually setting the $_FILES array but it didn't work...

$_FILES = [
        'csvfile' => [
            'tmp_name' => '/home/path/to/tests/Fixture/csv/test.csv',
            'name' => 'test.csv',
            'type' => 'text/csv',
            'size' => 335057,
            'error' => 0,
        ],
];
$this->post('/foo/bar');

What's the right way to do this?

2 Answers 2

2

Mocking core PHP functions is a little bit tricky.

I guess you have something like this in your posts model.

public function processFile($file)
{
    if (is_uploaded_file($file)) {
        //process the file
        return true;
    }
    return false;
}

And you have a corresponding test like this.

public function testProcessFile()
{
    $actual = $this->Posts->processFile('noFile');
    $this->assertTrue($actual);
}

As you do not upload anything during the test process, the test will always fail.

You should add a second namespace at the begining of your PostsTableTest.php, even having more namespaces in a single file is a bad practice.

<?php
namespace {
    // This allows us to configure the behavior of the "global mock"
    // by changing its value you switch between the core PHP function and 
    // your implementation
    $mockIsUploadedFile = false;
}

Than you should have your original namespace declaration in curly bracket format.

namespace App\Model\Table {

And you can add the PHP core method to be overwritten

function is_uploaded_file()
{
    global $mockIsUploadedFile;
    if ($mockIsUploadedFile === true) {
        return true;
    } else {
        return call_user_func_array('\is_uploaded_file',func_get_args());
    }
}

//other model methods

}  //this closes the second namespace declaration

More on CakePHP unit testing here: http://www.apress.com/9781484212134

Sign up to request clarification or add additional context in comments.

Comments

1

From what I can tell, CakePHP magically combines the contents of $_FILES, $_POST, etc so we access each from $this->request->data[...]. And you can pass info to that data array with an optional second parameter:

$data = [
        'csvfile' => [
            'tmp_name' => '/home/path/to/tests/Fixture/csv/test.csv',
            'name' => 'test.csv',
            'type' => 'text/csv',
            'size' => 45,
            'error' => 0,
        ],
];
$this->post('/foo/bar', $data);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.