I started working with Silex and it's just great. The problem appears when trying to proper unit test my classes. Concretely the closures :( In the following lines I explain my problem to see if any of you knows how to solve it. Please, do not focus on the syntax but the testing problem itself.
I have a provider like this:
<?php
namespace Foo\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Foo\Bar;
class BarProvider implements ServiceProviderInterface {
public function register( Application $app ) {
$app[ 'foo_bar' ] = $app->protect( function() use ( $app ) {
return new Bar( $app );
} );
}
public function boot( Application $app ) {}
}
Then I need to get an instance of the foo_bar element:
<?php
namespace Foo;
use Silex\Application;
class Clazz {
protected $bar;
public function __construct( Application $app ) {
$this->bar = $app[ 'foo_bar' ]();
}
}
This works just fine. The thing is that I'm developing using TDD (and PHPUnit) and It's impossible for me to proper test the Clazz class.
<?php
namespace Foo\Test;
use PHPUnit_Framework_TestCase;
use Silex\Application;
use Foo\Bar;
use Foo\Clazz;
class ClazzTest extends PHPUnit_Framework_TestCase {
public function testConstruct() {
$mock_bar = $this->getMock( 'Foo\Bar' );
$mock_app = $this->getMock( 'Silex\Application' );
$mock_app
->expects( $this->once() )
->method( 'offsetGet' )
->with( 'foo_bar' )
->will( $this->returnValue( $mock_bar ) );
new Class( $mock_app );
}
}
The problem here resides in the "()" after the $app[ 'foo_bar' ] in the Clazz class. When trying to execute the test I get a "PHP Fatal error: Function name must be a string in ..." error. I understand I cannot unit test the class this way but I don't see the proper way to do it.
How could I test this statement (because at the end the only complex statement is $this->bar = $app 'foo_bar' ; )?
Ok, I think I managed to test properly this closure! The final test looks like this:
<?php
namespace Foo\Test;
use PHPUnit_Framework_TestCase;
use Silex\Application;
use Foo\Bar;
use Foo\Clazz;
class ClazzTest extends PHPUnit_Framework_TestCase {
public function testConstruct() {
$mock_bar = $this->getMock( 'Foo\Bar' );
$mock_app = $this->getMock( 'Silex\Application' );
$mock_app
->expects( $this->once() )
->method( 'offsetGet' )
->with( 'foo_bar' )
->will( $this->returnValue( function() use( $mock_bar ) { return $mock_bar; } ) );
new Class( $mock_app );
}
}
Instead of returning the mock, I return a closure that returns the mock. This way I don't get the error while still working with the actual mock.
Can anyone tell me if this is a correct approach?
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