I’m getting started unit testing my PHP application with PHPUnit. I understand that it’s important for unit tests to run in isolation so you know where to look when a test fails. One thing I am struggling to understand is how to test subclasses in isolation from their parent. For example, most of my models extend a “base model” which has most of the features that a model should have.
<?php
class BaseModel
{
public function save($data) {
// write $data to the database
$dbAdapter->save($data);
}
}
class RegularModel extends BaseModel
{
public function save($data) {
// clean up $data before passing it to parent
if (isset($data['foo'])) {
unset($data['foo']);
$data['bar'] = 'foo';
}
parent::save($data);
}
}
# Unit Test
class RegularModelTest extends PHPUnit_Framework_TestCase
{
public function testSaveMethodCallsParent() {
$data = array('foo' => 'yes');
$model = new RegularModel();
$model->save($data);
// assert parent received data correctly
}
}
I’m not sure how to test my RegularModel without calling a bunch of unnecessary code. I’m also doing some autoloading so when it calls save on the parent, it will actually try to save to the test database. I’d rather mock this out since I don’t care about whether or not it actually writes to the database when I’m testing my RegularModel only when I am testing my BaseModel. Or am I thinking about this all wrong? What do you recommend when it comes to testing situations like this?
Your best bet is to mock the
$dbAdapterwhen testingRegularModel. While you are still executing the parent class’s code, that code really is part of theRegularModelunit due to the is-a relationship.The only way around it would be to provide a different implementation of
BaseModel. You can either run these tests in a separate process or use Runkit to swap in the other implementation at runtime. Both of these have drawbacks–complexity, performance degredation, and instability–that come at too high a price in my view.