CakePHP Component Testing: saving data does not work

Viewed 18

I have a component whose sole function is to save data to the database and recall it consistently. However, the tests that I'm writing for the component are failing to save new records. I assume this is probably because I need to mock the table somehow, but just adding the fixtures isn't cutting it. What am I missing? Here is my component:

<?php
declare(strict_types=1);

namespace Visualize\Controller\Component;

use Cake\Controller\Component;
use Cake\Log\Log;
use Cake\ORM\TableRegistry;

/**
 * Options component
 */
class OptionsComponent extends Component
{
    /**
     * Default configuration.
     *
     * @var array<string, mixed>
     */
    protected $_defaultConfig = [
        'model' => null,
        'option_key' => null,
    ];
    /**
     * @var \Cake\ORM\Table
     */
    private $Options;

    /**
     * @var string
     */
    private $Model;

    /**
     * @var string
     */
    private $OptionKey;

    /**
     * @param array $config Our configuration options
     * @return void
     */
    public function initialize(array $config): void
    {
        parent::initialize($config);
        $this->Options = TableRegistry::getTableLocator()->get('Options');
        if (!isset($config['model']) || !isset($config['option_key'])) {
            die('Please configure the Options component before proceeding.');
        }
        $this->Model = $config['model'];
        $this->OptionKey = $config['option_key'];
    }

    /**
     * Save associated option data from a form.
     *
     * @param array $data HTTP data payload.
     * @param int $object_id The newly created line item ID.
     * @return bool
     * @throws \Exception
     */
    public function saveOptionsForm(array $data, int $object_id): bool
    {
        if (!empty($data[$this->OptionKey])) {
            foreach ($data[$this->OptionKey] as $key => $value) {
                $this->saveOption($object_id, $key, $value);
            }
        }

        return true;
    }

    /**
     * @param int $id The option key to save
     * @param string $key The option value to save
     * @param mixed $value The model of the associated object
     * @param mixed|null $model The ID of the associated object.
     * @return bool
     */
    public function saveOption(int $id, string $key, mixed $value, mixed $model = null): bool
    {
        $option = $this->Options->newEmptyEntity();
        $option
            ->set('object_id', $id)
            ->set('object_model', $model ?? $this->Model)
            ->set('option_name', $key)
            ->set('option_value', $value);
        if (!$this->Options->save($option)) {
            Log::error('Unable to save option:' . print_r($option, true));

            return false;
        }

        return true;
    }
}

And here is my test code:

<?php
declare(strict_types=1);

namespace Visualize\Test\TestCase\Controller\Component;

use Cake\Controller\ComponentRegistry;
use Cake\TestSuite\TestCase;
use Visualize\Controller\Component\OptionsComponent;

/**
 * Visualize\Controller\Component\OptionsComponent Test Case
 */
class OptionsComponentTest extends TestCase
{
    /**
     * Fixtures
     *
     * @var array<string>
     */
    protected $fixtures = [
        'app.Options',
    ];

    /**
     * Test subject
     *
     * @var \Visualize\Controller\Component\OptionsComponent
     */
    protected $Options;

    /**
     * setUp method
     *
     * @return void
     */
    protected function setUp(): void
    {
        parent::setUp();
        $registry = new ComponentRegistry();
        $this->Options = new OptionsComponent($registry, [
            'model' => 'CartLines',
            'option_key' => 'cart_line_options',
        ]);
    }

    public function testSaveOption(): void
    {
        $this->assertTrue($this->Options->saveOption(
            1,
            'option_1',
            'value_1',
        ), 'Failed to save option.');
    }

    /**
     * tearDown method
     *
     * @return void
     */
    protected function tearDown(): void
    {
        unset($this->Options);

        parent::tearDown();
    }
}
0 Answers
Related