I'm currently working on an open source bundle for Symfony2, and really want it to be the dogs nadgers in terms of unit test coverage and general reliability, however I've run into a snag due to my lack of PHPUnit knowledge (or a complex scenario, who knows)..
At present, I have a Mailer class, for handling individual mail scenarios. It looks a bit like this:
<?php
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\Routing\RouterInterface;
class Mailer
{
protected $mailer;
protected $router;
protected $templating;
protected $parameters;
public function __construct($mailer, RouterInterface $router, EngineInterface $templating, array $parameters)
{
$this->mailer = $mailer;
$this->router = $router;
$this->templating = $templating;
$this->parameters = $parameters;
}
}
Simple enough, got some Symfony2 interface gubbins in there to handle different routing and templating systems, happy happy joy joy.
Here's the initial test I tried setting up for the above:
<?php
use My\Bundle\Mailer\Mailer
class MailerTest extends \PHPUnit_Framework_TestCase
{
public function testConstructMailer
{
$systemMailer = $this->getSystemMailer();
$router = $this->getRouter();
$templatingEngine = $this->getTemplatingEngine();
$mailer = new Mailer($systemMailer, $router, $templatingEngine, array());
}
protected function getSystemMailer()
{
$this->getMock('SystemMailer', array('send');
}
protected function getRouter()
{
$this->getMock('RouterInterface', array('generate');
}
protected function getTemplatingEngine()
{
$this->getMock('RouterInterface', array('render');
}
}
The problem here is that my mock objects do not implement Symfony\Bundle\FrameworkBundle\Templating\EngineInterface and Symfony\Component\Routing\RouterInterface, so I can't use any mock objects that I create myself. One method I have tried is creating an abstract class which implements the correct interface on the test page, however the getMockForAbstractClass fails, stating it can't find the class...
When mocking you need to use the full qualified class path as the mock functionality is not taking the namespace of the calling code or any "use" statements into consideration.
Try
->getMock('\\Symfony\\Component\\Routing\\RouterInterface');
and leave out the second parameter. Usually specifying the methods does a lot more worse than good. Only if you want all the other methods to work like before than you should need the second parameter.
<?php
namespace bar;
class MyClass {}
namespace foo;
use \bar\MyClass;
class MockingTest extends \PHPUnit_Framework_TestCase {
public function testMock() {
var_dump($this->getMock('MyClass') instanceOf MyClass);
var_dump($this->getMock('\\bar\\MyClass') instanceOf MyClass);
}
}
Produces:
/phpunit.sh --debug fiddleTestThree.php
PHPUnit @package_version@ by Sebastian Bergmann.
Starting test 'foo\MockingTest::testMock'.
.bool(false)
bool(true)
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