Object-oriented – OOP for unit testing : The good, the bad and the ugly

object-orientedunit testing

I have recently read Miško Hevery's pdf guide to writing testable code in which its stated that you should limit your classes instanciations in your constructors. I understand that its what you should do because it allow you to easily mock you objects that are send as parameters to your class. But when it comes to writing actual code, i often end up with things like that (exemple is in PHP using Zend Framework but I think it's self explanatory) :

class Some_class
{
    private $_data;

    private $_options;

    private $_locale;

    public function __construct($data, $options = null)
    {
        $this->_data = $data;

        if ($options != null) {
            $this->_options = $options;
        }

        $this->_init();
    }

    private function _init()
    {
        if(isset($this->_options['locale'])) {
            $locale = $this->_options['locale'];

            if ($locale instanceof Zend_Locale) {
                $this->_locale = $locale;
            } elseif (Zend_Locale::isLocale($locale)) {
                $this->_locale = new Zend_Locale($locale);
            } else {
                $this->_locale = new Zend_Locale();
            }
        }
    }
}

Acording to my understanding of Miško Hevery's guide, i shouldn't instanciate the Zend_Local in my class but push it through the constructor (Which can be done through the options array in my example).

I am wondering what would be the best practice to get the most flexibility for unittesing this code and aswell, if I want to move away from Zend Framework.

Thanks in advance

Best Answer

You are absolutely right, you should not hard-code a reference to Zend in the method.

You need a seam, a layer of abstraction, so that you can pass in Zend or any other framework. I don't know if PHP has a concept of interfaces, but those are a popular way to abstract implementations out of code.

I'd recommend Michael Feathers' book "Working Effectively with Legacy Code" for a detailed discussion of the topic.

Related Topic