0

Using Laravel framework with phpunit for unit tests.

I am working with a function that requires directories to be created for a file to be written to it, in short, the function gets data, write it to a temp file and moves the temp file once done.

public function getDataAndStoreToCSVFile() {
    Log::info(date('Y-m-d H:i:s') . " -> " . __FILE__ . "::" . __FUNCTION__);
    try {
        // make sure directories exist
        if (!Storage::has($this->temporary_directory) || !Storage::has($this->storage_directory)) {
            $this->createDirectories();
        }

        // get full path of storage disk for files
        $diskPath = Storage::getAdapter()->getPathPrefix();

        // create a complete path to temporary file to allow tempnam to find the directory
        $full_temporary_file_path = $diskPath.$this->temporary_directory;

        // fetch stations, station networks and station params seperated by double new line,
        // will return FALSE if something is missing and file will not be created and not written to
        if($stations_data_array = $this->getCompleteStationsDataArray("\n\n")){

            // create temporary file
            $temporary_file = tempnam($full_temporary_file_path,'') ;

            // if both $temporary_file and $stations_data_array exist write entries to file one at a time in CSV format
            if (file_exists($temporary_file)) {
                $fp = fopen($temporary_file, 'a');
                foreach ($stations_data_array as $fields) {
                    if (is_object($fields) || is_array($fields)) {

                        // $fields is an array
                        $fields = (array)$fields;
                        fputcsv($fp, $fields);
                    } else {

                        // $fields is the separator
                        fwrite($fp, $fields);
                    }
                }

                // done writing, close file
                fclose($fp);

                // create new permanent name for $temporary_file in the storage directory "full_disk_path.storage_path.yyyymmddhhmmss.timestamp"
                $storage_file = $diskPath . $this->storage_directory . "/" . date('YmdHis') . "." . time();

                // rename $temporary_file to $storage_file
                if (!rename($temporary_file, $storage_file)) {
                    Log::error(__FILE__ . "::" . __FUNCTION__ . " : Failed to move temporary file from " . $this->temporary_directory . " to " . $this->storage_directory);
                }
            } else{
                Log::error(__FILE__ . "::" . __FUNCTION__ . " : Temporary file was not available or does not exist.");
            }
        } else {
            Log::error(__FILE__ . "::" . __FUNCTION__ . " : Temporary file was not created.");
        }
    } catch (\ErrorException $e) {
        // Catches missing directory or file, or tempnam couldn't find temporary storage path //Todo add test for this exception
        Log::error(__FILE__ . "::" . __FUNCTION__ . " : " . $e->getMessage());
    } catch (\Exception $e) {
        // Catches uncaught exceptions
        Log::error(__FILE__ . "::" . __FUNCTION__ . " : " . $e->getMessage());
    }
}

To test if ErrorException is thrown when directories are missing, this test :

public function test_getDataAndStoreToCSVFile_handles_ErrorException() {

    // set up data
    $this->setup_all_data_for_getDataAndStoreToCsvFile_funtion();

    // mock class
    $mock = $this->getMockBuilder('App\Interfaces\Sources\IdbStationSourceInterface')

    // stub function createDirectories, will now return null and not create directories, missing directories will throw ErrorException
    ->setMethods(['createDirectories'])
    ->getMock();

    // expect the ErrorException to be thrown
    $this->expectException('ErrorException');

    // run function
    $mock->getDataAndStoreToCSVFile();
}

When I run the test, my logs indicate that I fell into :

} catch (\ErrorException $e) {
        // Catches missing directory or file, or tempnam couldn't find temporary storage path //Todo add test for this exception
        Log::error(__FILE__ . "::" . __FUNCTION__ . " : " . $e->getMessage());
}

But my terminal says :

1) Tests\Interfaces\Sources\IdbStationSourceInterfaceTest::test_getDataAndStoreToCSVFile_handles_ErrorException Failed asserting that exception of type "ErrorException" is thrown.

I have no clue where to go from there, I read and tried a couple of things but clearly I'm doing something wrong.

Edit 1 :

Tried : $this->setExpectedException("ErrorException");

But I get the following :

1) Tests\Interfaces\Sources\IdbStationSourceInterfaceTest::test_getDataAndStoreToCSVFile_handles_ErrorException Error: Call to undefined method Tests\Interfaces\Sources\IdbStationSourceInterfaceTest::setExpectedException()

2
  • Try $this->setExpectedException("ErrorException"); Commented Oct 19, 2017 at 15:02
  • @ishegg Thx for the reply, I modified the question to include your code, it didn't work out. Commented Oct 19, 2017 at 15:06

2 Answers 2

3

Thats because you catched the exception. PHPUnits expectedException-method only registers unhandled or rethrown exceptions. Either rethrow the exception in your catch-block or just test for the log-entry you are creating in the catch-block.

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

Comments

0

from function getDataAndStoreToCSVFile() you just throw error with error code and message. Then you can use these assertion in test case.

/** *@expectedException ExampleException *@expectedExceptionCode ExampleException::EceptionCode */ public function test_getDataAndStoreToCSVFile_handles_ErrorException() {}

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.