Unit testing a symfony service class with phpunit - symfony

I have a basic class GenericHelper.php in directory Foo/BarBundle/Helper
I registered it as a service in Foo/BarBundle/Resources/config/services.yml:
parameters:
generic_helper.class: Foo\BarBundle\Helper\GenericHelper
services:
generic_helper:
class: %generic_helper.class%
and I'm able to access it in a command by doing the following:
$helper = $this->getContainer()->get('generic_helper');
Now, I'd like to unit test that class with PHPUnit; I have the following code (similar to http://symfony.com/doc/2.0/book/testing.html#unit-tests):
namespace Foo\BarBundle\Tests\Helper;
use Foo\BarBundle\Helper\GenericHelper;
class GenericHelperTest extends \PHPUnit_Framework_TestCase {
public function testSomeMethod() {
$helper = new GenericHelper(); //line 10
$this->assertEquals($helper->someMethod(), SOME_RESULT);
}
}
Running PHPUnit results in the following error:
PHP Fatal error: Class 'Foo\BarBundle\Helper\GenericHelper' not found in /DIR/src/Foo/BarBundle/Tests/Helper/GenericHelperTest.php on line 10
Grepping for 'GenericHelper' only yields a few results:
the Class itself and the Test class
the services.yml file
appDevDebugProjectContainer files in app/cache/dev/, which have all the service getters
Question(s):
Does Symfony prevent PHPUnit from directly constructing a service class?
Is there a way to do this without creating a Symfony Container then accessing the service (as done here: Access Symfony 2 container via Unit test?)? I mean, it's still just a basic class...

Running phpunit with the -c flag pointing to the directory containing the phpunit.xml.dist file solved the issue. Doing this includes bootstrap.php.cache and therefore the autoloading stuff necessary.

Related

bundle's service (autowire) not available in controller's method

I'd like to use https://github.com/tedious/TedivmStashBundle bundle in my symfony 4 project. Added by composer, configured in /config/stash.yaml file and according to the profiler bar, it's working basically.
Now, I want to use to caching values in my controller. I've try to add the service stash by its name to the method's parameter, using the same name as the example says:
$pool = $this->container->get('stash');
but the framework did not find the service. It can't be added like the example explained neither.
How can I use this bundle as a service (autowired) in my symfony 4 app?
UPDATE
services.yaml:
stash.default_cache:
class: Tedivm\StashBundle\Service\CacheService
public: true
arguments:
$name: 'stash'
Tedivm\StashBundle\Service\CacheService: '#stash.default_cache'
Controller:
public function something(Request $request, CacheService $service, ...
It's looks like working now :)
Thanx for the suggestion (and the correct solution later) to #Cerad
Here is an example of how to approach this sort of problem when dealing with bundles that are not quite ready for autowire.
Start by installing a test project:
symfony new --full stash --version=lts
composer require tedivm/stash-bundle
Note that the bundle does not directly support Symfony 5 hence the lts. Note also that the bundles does not support Flex so you have to add your own config/packages/stash.yaml file per the bundle's readme file.
# config/packages/stash.yaml
stash:
drivers: [ FileSystem ]
FileSystem: ~
At this point we can determine which service we need to inject:
bin/console debug:container stash
Information for Service "stash.default_cache"
=============================================
Class CacheService
---------------- -----------------------------------------
Option Value
---------------- -----------------------------------------
Service ID stash.default_cache
Class Tedivm\StashBundle\Service\CacheService
Most of the time you would like to use an interface for injection but a peek at the source code reveals that the bundle does not use interfaces. As a side note, calling a third party service 'stash' is not a good idea. It really should have been 'tedivm.stash' but I digress.
We can now create an alias and then typehint against it:
# config/services.yaml
Tedivm\StashBundle\Service\CacheService : '#stash' # alias for typehinting
# Controller class
public function index(CacheService $cacheService)
{
return new Response('Cache ' . get_class($cacheService));
}
And that should do it.

Definine a synthetic service in Symfony 4.1 doesn't work from within a bundle

I am creating a Symfony Bundle that defines a synthetic service:
my_alias:
public: true
synthetic: true
After installing the bundle, the application's console command cache:clear always fails with the error:
[Symfony\Component\DependencyInjection\Exception\RuntimeException]
Invalid service "my_alias": class "" does not exist.
If I create the same alias inside the actual framework, this error does not turn up.
Is this a bug, or am I doing something wrong?
When you clear the cache the kernel is recompiled and the container will not figure out your service that is not injected to the container, that's why you need to inject it under your Kernel class:
if (!$container->hasDefinition('my_alias')) {
$container->set('my_alias', new SyntheticService());
}

`FeatureContext` context class not found and can not be used.

I'm new with symfony2 and i wnat to test my app using behat but when I followed the official install in this link http://docs.behat.org/en/latest/cookbooks/1.symfony2_integration.html#installing-and-enabling-symfony2-extension
i got this error :
[Behat\Behat\Context\Exception\ContextNotFoundException]
FeatureContext context class not found and can not be used.
it was just after the first line and when i ran the bin/behat command.
When using the Symfony2Extension, you are responsible for handling the autoloading. Make sure the FeatureContext class can be autoloaded by changing your composer.json autoload configuration and running composer dump-autoload.

How to call Doctrine CacheProvider function in Laravel 4 Controller

I have seen some useful functions like the following in
vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php of laravel 4 installation.
public function flushAll()
{
return $this->doFlush();
}
How can I call this function from my controller.
This question was asked in Laravel Forum and here also, but no response!
Luckily I have derived solution for my question.
The Composer vendor have a class autoload map file which have an array with all class names with their namespace.
This file will be updated in all instance of composer install or composer update which will be prepeded by composer dump-autoload command.
If I am making a class somewhere, I have to execute the php artisan dump-autoload command to properly auto-load them.
So here in vendor/composer/autoload_classmap.php, we have reference to all vendor classes including Symfony and Doctrine.
And the entry for the Doctrine Cache Provider will be,
'Doctrine\\Common\\Cache\\CacheProvider' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php'
Here I can see which file it is, and what will be the namespace.
Now we can call functions by using the namespace,
use Doctrine\Common\Cache\CacheProvider as DoctrineCache;
DoctrineCache::flushAll();
And also we can add this in providers array with app.php

I am trying to unit test a Silex application but Silex\WebTestCase namespace cannot be found

I have phpunit 3.6.12 installed as well as Silex. In the root directory of my app I have tests directory which contains the trivial test file BlogFunctionTest.php
<?
use Silex\WebTestCase;
// BLOG: Front end test
class BlogFunctionalTest extends Silex\WebTestCase
{
public function testIndex()
{
$this->assertGreaterThan(0, 1);
}
}
?>
when I run phpunit from the command line I get the error
PHP Fatal error: Class 'Silex\WebTestCase' not found in {path}/BlogFunctionTest.php line 7
which refers to the line where I try to extend WebTestCase. The same happens if I replace
use Silex\WebTestCase;
with
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
Silex is installed in relative to my test file at
../vendor/silex/
Any tips are greatly appreciated, thank you!
you have to define a bootstrap inside phpunit.xml.dist which point to the bootstrap of your silex application like it's done here https://github.com/joshuamorse/Silex-Boilerplate/blob/master/phpunit.xml.dist

Resources