2

I'm attempting to write unit tests for my EE module using Mockery. Throughout my module code I have lines like:

$this->EE->db->select('channel_title, channel_id');
$this->EE->db->from('exp_channels');
$query = $this->EE->db->get();

Of course when I am attempting to test my functions I don't want to actually load the EE framework, I rather want this db object to be a mock. But I can't set variables on mocks, so Mockery can't tell the function under test that when it looks at EE->db it should actually use my mock. Based on this answer it seems like in order to use Mockery I'll have to rewrite the above code to:

function db() { return $this->EE->db}

db()->select('channel_title, channel_id');
db()->from('exp_channels');
$query = db()->get();

Is this my only option? Have I missed some trick for how to get Mockery to mock variables too?

2

Yeah, that's one of your options. It's almost pointless testing code that way though, it would be very brittle. However, to get Mockery to access the global EE object, you simply need to set it up in your class's constructor:

public function __construct($ee = null)
{
    $this->EE = $ee ?: get_instance();
}

That way, in your unit tests, you can inject the dependency like so:

$mock_ee = m::mock('ee');
$mock_ee->db = m::mock('ee_db');

$module = new My_module($mock_ee);
// tests here

The other alternative is you will need to spin up most of the EE core inside your unit tests, and tie it to a real database. Ideally reset the test database at the start of each test run, and run each test inside a transaction so that it doesn't affect your data. I'd definitely recommend this method rather than trying to mock the entire database object, because then you are testing the outcome of the function rather than just the contents of the function.

I haven't yet figured out the easiest way to do this (bootstrap EE from the console without rendering a page), but I'm sure it would be possible without too much work.

In Store 2, I solved this problem by using the Eloquent ORM to handle the database layer. In the unit tests, I simply load Eloquent and connect it to a test database, without loading the rest of EE. Then I stub out any other calls to EE libraries using Mockery.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.