I'm trying to improve the following code for testability.
public function can_apply_extension()
{
$search_dates = [
Carbon::createFromTimestamp(strtotime($this->billing_verified_to))->subMonth(1),
$this->billing_verified_to
];
$record = ORM::factory('a model')
->where('created_at', 'BETWEEN', $search_dates)
->find();
if( !$record->loaded() )
{
return true;
}
return false;
}
Here's how I think I can improve it:
public function can_apply_extension($search_from = null, $search_to = null)
{
$search_from = is_null($search_from) ? Carbon::createFromTimestamp(strtotime($this->billing_verified_to))->subMonth(1) : $search_from;
$search_to = is_null($search_to) ? $this->billing_verified_to : $search_to
$search_dates = [$search_from, $search_to];
$record = ORM::factory('a model')
->where('created_at', 'BETWEEN', $search_dates)
->find();
if( !$record->loaded() )
{
return true;
}
return false;
}
I still have to mock ORM part. I think the only option is that I pass an object as a parameter or make a method that injects the ORM object.
Are there any other better ways? I'm aware of IoC container, but I can't use it in our current environment.
Update: Beside passing ORM as a parameter so that I can just swap it out, I found another workaround.
Since ORM::factory()
actually returns an object, I was able to add a method and modify the factory method.
public function testing($bool)
{
$this->_testing = $bool;
}
public function instead($when_this_passed, ORM $use_this_instead)
{
$this->_instead_map[$when_this_passed] = $use_this_instead;
}
public function factory($name)
{
if($this->_testing && array_key_exists($name, $this->_instead_map))
{
return $this->_instead_map[$name];
}
else
{
parent::factory($name);
}
}
ORM::factory
implies a static property that holds a reference to an object. Testing classes with static properties is hard... really hard \$\endgroup\$