Aleksandr Makov
Aleksandr Makov

Reputation: 2938

PHPUnit: how can you test method with class instantiation?

I have a simple class like:

class Subject {
    /** @var ValueObject[] */
    private $collection = [];

    function addToCollection (array $whatver) {
        if (array_key_exists($whatever, 'smth')) {
            $collection[] = new ValueObject($whatever);
            return true;
        }
        return false;
    }
}

I know I could simply pass ValueObject to the method, but real life addToCollection() is a bit more complex.

Is it at all possible to test this method with PHPUnit or I should redo it with DI in mind?

Thanks

Upvotes: 4

Views: 2088

Answers (2)

Aleksander Wons
Aleksander Wons

Reputation: 3967

In your case I would say it is easy to test this class. You have a method that returns bool on success. You don't have any getters or setters so all you need to check is the return value from your method. Everything else is an implementation detail so there is no need to test it.

If you have there dependencies you can mock them through the constructor, but it changes nothig from the perspective of you add method.

Another suggestion is think about single responsibility principle. You are adding something to the collection but also do some magic before you create the object. Move the creation of the object to another class (like factory) and keep your class simple - just add the object to the collection. With this approach you won't have and dependencies and your code will be easy to test.

Upvotes: 3

gontrollez
gontrollez

Reputation: 6538

You can build the ValueObject instances using an externally injected Factory. A default ValueFactory can be created internally if none is injected:

class Subject {

    /** @var ValueObject[] */
    private $collection = [];

    /** @var ValueFactory */
    private $valueFactory;

    public function getValueFactory() {
        if (!isset($this->valueFactory)) {
            $this->valueFactory = new ValueFactory();
        }
        return $this->valueFactory;
    }

    public function setValueFactory(ValueFactory $factory) {
        $this->valueFactory = $factory;
    }

    function addToCollection (array $whatever) {
        if (array_key_exists($whatever, 'smth')) {
            $collection[] = 
                $this->getValueFactory()->buildValueObject($parameters);
            return true;
        }
        return false;
    }
}

Now in your test you can mock a ValueFactory and inject it to Subject, so you can check how instances are created and get control over returned ValueObject instances.

Upvotes: 0

Related Questions