Here is the class I am unit testing. Currently I am testing the doSomething
function:
class FooClass {
public function doSomething( $user ) {
$conn = $this->getUniqueConnection( $user->id );
$conn->doSomethingDestructive();
}
private function getUniqueConnection( $id ) {
return new UniqueConnection( $id );
}
}
As you can see, the doSomething
function gets a new instance of UniqueConnection
(a class I am not testing here) based on a property of the argument it receives. The problem is that UniqueConnection:: doSomethingDestructive
method is something I cannot call during tests due to its... destructiveness. So I would like to stub/mock the UniqueConnection
rather than use a real one.
I don't see any way to inject my mocked UniqueConnection
. I would make the UniqueConnection
a constructor argument for FooClass
but, as you can see, a new one gets created based on the parameter to the doSomething
function and all the unique ids it may be called with are not known ahead of time.
My only option that I can see is to test a mock of FooClass
instead of FooClass
itself. Then I would replace the getUniqueConnection
function with one that returns a mock/stub. This seems bad to test an mock, but I don't see any way to achieve what I am after otherwise. UniqueConnection
is a third party vendor library and cannot be modified.
You could make a UniqueConnectionFactory
, and pass an instance of that to FooClass. Then you have
private function getUniqueConnection( $id ) {
return $this->uniqueConnectionFactory->create( $id );
}
In general, this is one of the benefits of using a factory - you keep the new
operator out of the class, which allows you to more easily vary the object being created.
Like Rambo Coder said, it's a matter of doing too much in your class. I wouldn't go as far as wanting to create a Factory, especially if you'll only ever create an instance of one specific class. The simplest solution would be to invert the responsibility of creating the UniqueConnection:
<?php
class FooClass {
public function doSomething( UniqueConnection $connection ) {
$connection->doSomethingDestructive( );
}
}
Pass a mock when you're testing, pass a new UniqueConnection( $user->id )
in the real code..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With