I have the following code:
class Plugin {
protected $manager;
public function activate(Composer $composer, IOInterface $io)
{
$this->manager = new Manager();
$this->doSomething($this->manager);
}
private function doSomething(Managaer $manager)
{
$manager->add('first', function() {
//do something.
});
$manager->add('second', function() {
//do something.
});
}
}
How can I assert that the add method was called on the Manager class?
The Plugin class is instantiated for me and cannot have dependencies injected. The activate method is also called for me (not in my control), so I cannot pass in dependencies.
I usually test this by having the following extra method and mocking it to return a mocked instance of Manager
class Plugin {
protected $manager;
public function activate(Composer $composer, IOInterface $io)
{
$this->doSomething($this->getManager());
}
private function doSomething(Manager $manager)
{
$manager->add('first', function() {
//do something.
});
$manager->add('second', function() {
//do something.
});
}
public function getManager()
{
return new Manager;
}
}
And that would look like the following:
//get a mock manager
$manager = $this->getMock('Manager');
//assert that method should be called
$manager->expects($this->once())
->method('add')
->with($this->isInstanceOf('Closure'));
//create mock plugin but only mock getManager method
$plugin = $this->getMock('Plugin');
$plugin->expects($this->once())
->method('getManager')
->will($this->returnValue($manager));
$plugin->activate(/** args **/);
This to me, feel hacky. I don't feel like I should be mocking the Plugin class. How do other people tackle this issue?
Do you have a setter & a getter for the Manager? where if a class variable is not set, return a default instance. This way in the tests I can call the setManager() method with a mocked instance?
That also doesn't sound great because I'm writing extra code just to unit test the class!
Aucun commentaire:
Enregistrer un commentaire