require_once in class breaks Unit Test - phpunit

I use this at the top of my class, that I run a test against:
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
require_once ExtensionManagementUtility::siteRelPath('my_ext') . 'Lib/ServiceLoader.php';
class Tx_MyOtherExt_Domain_Service_SearchService implements SingletonInterface
Then in my test I get an instance of that class, like this:
/** #var \Tx_MyOtherExt_Domain_Service_SearchService $service */
$service = GeneralUtility::makeInstance('\Tx_MyOtherExt_Domain_Service_SearchService');
However, the test throws an error:
Fatal error: main(): Failed opening required 'typo3conf/ext/my_ext/Lib/ServiceLoader.php' (include_path='C:/xampp/htdocs/my_proj/site/typo3/contrib/pear/;.;C:\xampp\php\PEAR')
How can I add the site root to the include path? The PHPSTORM settings (Settings->PHP) don't seem to make a difference.
NOTE: adding the site root to the include_path setting in php.ini works, of course. But as this path changes per project, setting this via PHPSTORM would be best.

How about using the constant PATH_site to get an absolute path?
https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/GlobalValues/Constants/Index.html

There are several things you should improve writing your code. First of all, it is also about changing the running code.
Use injection
If you need a separate class in your code, use e.g. constructor injection to inject the object into a property. By calling $this->getAccessibleMock with the 5th argument to false the original constructor won't call and you can fake the object by using `->_set('name', $obj)``
GeneralUtility::makeInstance
Don't use that in the tests but new(). If the tests breaks, your code is wrong and should be changed instead of building the test's code around it!

Related

Loading Fixtures for functional tests in Symfony 2: Call to undefined method MyControllerTest::loadFixtures())

I am trying to find the easy way to load my fixtures in Symfony 2.6 to run functional tests. This is a quite common question, and has been asked a few times, but the answers I have found so far do not quite reach my expectations:
Some rely on running the command line from inside the functional test.
Other run manually each one of the defined fixtures, and then take care of creating and deleting the database.
There is a lot of overhead in both cases (use statements and manual code), for a task that I believe is very standard.
On the other hand, these same posts recommend the LiipFunctionalTestBundle. Going for it, here is what I read in the installation instructions:
write fixture classes and call loadFixtures() method from the bundled
Test\WebTestCase class. Please note that loadFixtures() will delete the contents from the database before loading the fixtures."
So I tried...
namespace AppBundle\Test\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class MyControllerTest extends WebTestCase
{
public function setUp()
{
$classes = array(
'AppBundle\DataFixtures\LoadUserData',
);
$this->loadFixtures($classes);
}
...
}
With no luck:
Call to undefined method AppBundle\Tests\Controller\MyControllerTest::loadFixtures() in /gitrepos/myproject/src/AppBundle/Tests/Controller/MyControllerTest.php on line 15
a static call gives the same error...
self:loadFixtures($classes);
I really think I am missing something pretty obvious. Anyone can get me back on track ?
I can see you're using
Oro\Bundle\TestFrameworkBundle\Test\WebTestCase
as the base class while I think you should use
Liip\FunctionalTestBundle\Test\WebTestCase
to be able to call this method.

trying to use Symfony component and having name space issues

So i am starting a new project and want to use some of the Symfony Components. I have not used name spaces before with PHP, put i am familiar with the concept from my work in java.
i have this simple piece of code and when i run it i get the error:
PHP Fatal error: Class 'Symfony\Component\CssSelector\XPath\Translator' not found in /home/me/scrapes/Symfony/Component/CssSelector/CssSelector/CssSelector.php on line 52
I am thinking it my lack of knowledge of the name space thing.
/home/me/scrapes/Symfony/Component/CssSelector/CssSelector/XPath/Translator.php does exist.
<?php
set_include_path('/home/me/html/inc');
require 'functions.php';
require 'Symfony/Component/DomCrawler/Crawler/Crawler.php';
require 'Symfony/Component/CssSelector/CssSelector/CssSelector.php';
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\CssSelector\CssSelector;
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
print $crawler->filter('body > p')->text();
curl_close($ch);
require 'cleanup.php';
?>
thanks for any help
I think this is caused because, if you look in the files you required (for example Symfony/Component/DomCrawler/Crawler/Crawler.php) you'll see that those files use their own use statements (to load other classes).
Namespaces
Let's start with the namespaces. A namespace is used to easily create classes with the same name in different packages. Let's say I have a package called Foo and a package called Bar. Both packages contain a Client class that is used to do some client work (one to call the Google Maps API for example and the other to call the Facebook Graph API). Let's also assume neither of the packages uses namespaces.
If I execute the following code:
<?php
require 'Foo/Client.php';
require 'Bar/Client.php';
This is not going to work, because both packages declare a Client class. Oops, how is PHP going to know which Client class to use if you do this?
<?php
$client = new Client();
It's not going to know which Client to use, so it gives up and throws an error.
If you use namespaces (declared using the namespace keyword in PHP at the top of your file, directly below <?php) you can prevent this from happening. The Foo package can create a Client class in the Foo namespace and the Bar package in the Bar namespace. Now we can
actually use both files and create a client:
<?php
require 'Foo/Client.php'
require 'Bar/Client.php'
$fooClient = new Foo\Client();
$barClient = new Bar\Client();
This will work fine.
I think you might have encountered the Foo_Client notation in older PHP libraries. This is an old way to create namespaces before PHP natively supported them.
"But", I hear you say, "it's quite cumbersome to write Foo\Bar\Baz\Client() every time I want to instantiated a class".
It is, and that's where the use keyword comes in. When using the use keyword, I can tell PHP I want to use a specific client and just use the class name, like so:
<?php
require 'Foo/Bar/Baz/Client.php'
use Foo\Bar\Baz\Client;
$client = new Client();
This will work, if you use the use Foo\Bar\Baz\Client statement, because you tell PHP "Okay, I want to use the Client class from the Foo\Bar\Baz namespace to be used when I use the Client class.
Autoloading
Now, what happens if you use a lot of different classes and you seperated them into several files (which you should do). You get a lot of different require and use statements on the top of a file. That's where autoloading comes in.
There has been a spl_register_autoloader function for quite some time in PHP. This function is used by PHP to find out which files to use when you instantiate a class that is not known because you did not require the file. This function is used both when creating a class, or, and this is the key part when you use a class.
And that's what's happening in your code. You don't have an autoloader registered that can translate the use statements in the files you required to actual class declarations.
Great, how do I fix it?
To fix it, I suggest you read up on the PHP-FIG and PSR-4. These people created standards (which you can follow but are not obliged to). To create easy to use libraries, such as the Symfony component. After you've done that, read up on Composer. After you've done this, you can drop the require statements from your code and use Composer to autoload all the classes you need.

What is best way to add additional object classes to my symfony2 controller files?

I'm relatively new to Symfony2, so I'm learning by doing. My controller classes are getting pretty big. I'd like to break it up with functions() or objects->method(). Unfortunately I can't figure out where to put the code. (actually its really simple functions... but I can wrap that in an object...)
--I can't add it to the bottom of my DefaultController.php file. It errors out, and not pretty code to boot, either inside or outside of the { }.
--I can't simply add a new NewObject.php file to the controller directory. That errors out. The error: FatalErrorException: ...NewObject not found.
--I've toyed with manual mods to ../app/autoload.php but that doesn't really make sense for a simple class add to my ./SRC/ bundle. Perhaps I should build a ./src/autoload.php file (similiar to ./vender/autoload.php) but the contents of that file don't make sense to me at all. I simply can't figure out how the AnnotationRegistry Loader works.
Am I missing something? This seems way too hard.. what I want is a wrapped up 'include' so I can use the class in dev and after deployment.
How do I include NewObject.php (and the accompanying $newObject->function() ) in my code?
I'm told I can add a service, yet that seems like outrageous overhead for such a seemingly simple task (again, all I'm trying to do is clean up my very long controller php code...)
thanks in advance for your advice.
So you've got a project structure that looks something like this, right?
project
-- app
-- bin
-- src
-- SomeName
-- SomeBundle
-- Controller
-- Entity
-- Resources
-- ...
-- vendor
-- web
And you're just looking to have some kind of "helper" class that's used throughout your bundle. Is that correct?
If so, then you can really put it wherever you want to inside your src/ directory... Just make sure that the class name matches the file name, and that the path to the file matches the namespace you define at the top of your PHP code.
Sometimes when I do this, I'll create a simple directory under my bundle called "Helper/". Other times, when the application is more complex, I might be a little bit more explicit. But here's what the first case would look like...
First, add your /Helper directory under your bundle, and create the class file:
project
-- app
-- bin
-- src
-- SomeName
-- SomeBundle
-- Controller
-- Entity
-- Helper
-- SomeHelper.php
-- Resources
-- ...
-- vendor
-- web
The contents of SomeHelper.php might look like this:
<?php
namespace SomeName\SomeBundle\Helper;
class SomeHelper
{
public function doSomething()
{
...
}
}
Because your namespace matches the file path, it gets autoloaded, so you don't need to worry about include statements. You can instantiate that class anywhere in your bundle, as long as you include a use statement:
<?php
namespace SomeName\SomeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use SomeName\SomeBundle\Helper\SomeHelper;
class DefaultController extends Controller
{
public function indexAction()
{
...
$helper = new SomeHelper();
$helper->doSomething();
...
}
}
Regarding the usage of services... Yes, that might be overkill, depending on what you're using it for. It's helpful to create services when the class needs to be aware of the application around it. For example, if you're creating a service that emails a User, it might want to access your database through the Doctrine service, or it might want to log the email activity through the Monolog service.
However, if your class doesn't need to know about the application (referred to as the "service container"), for example if it's just used to transfer data, then a helper class is probably more appropriate.

PHPUnit Mock Object replacing Real Class

I have a couple of tests in my test suite being run in Zend_Test
One test creates a mock of Foo_Bar_Baz via PHPUnit's MockBuilder as that class its dependency. Now in the test for Foo_BAR_baz (the change in case is on purpose and is necessary due to autoloading), I am not getting the class but rather an instance of the mock, which obviously doesn't work.
Doing a var_dump on the object results in class Foo_Bar_Baz#27115(0) { } so it appears to be creating an instance of the mock.
Fixing the case of in the mock gets things to work as expected. I have never seen this behavior in mocking objects before. For some reason the mocked class is being loaded into PHP so that when the next test tries to instantiate the real object it instantiates the mock instead. Why would this be happening?
Class names in PHP are not case-sensitive, but filenames on a *nix server are.
I suspect the change in case is causing a change in behaviour because of an autoload mechanism; PHP would only autoload one of Foo_Bar_Baz.php and Foo_BAR_Baz.php.
In your case, if you have already defined a class Foo_BAR_Baz (as a mock) then PHP will use the same definition for Foo_Bar_Baz, thereby ignoring your real class definition.

Getting error: Non-static method Phactory\Sql\Phactory::reset() should not be called statically

I have a trivially small PHPUnit test that looks like this:
<?php
namespace VNN\PressboxBundle\Tests\Entity;
namespace VNN\PressboxBundle\Entity;
use VNN\PressboxBundle\Entity\User;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Phactory\Sql\Phactory;
class UserTest extends EntityTest
{
public function testCreate()
{
Phactory::reset();
}
}
When I try to run it, I get this:
There was 1 error:
1) VNN\PressboxBundle\Entity\UserTest::testCreate
ErrorException: Runtime Notice: Non-static method Phactory\Sql\Phactory::reset() should not be called statically, assuming $this from incompatible context in /Users/jason/Web/pressbox/src/VNN/PressboxBundle/Tests/Entity/UserTest.php line 13
What's up with that? All the docs call it statically.
I'm doing this on Symfony 2.0, if that makes a difference.
The documentation says you should be using the top-level Phactory class directly under lib/--not the individual implementations such as Phactory/Sql/Phactory which get instantiated based on the PDO object you pass to setConnection. Change
use Phactory\Sql\Phactory;
to
require_once 'Phactory/lib/Phactory.php';
The main class is in the global namespace and doesn't require a use statement.
https://github.com/chriskite/phactory/issues/30
From the code, setConnection, define and create are not static functions but the README and website guide do not reflect that.
e.g. test code
https://github.com/chriskite/phactory/blob/next/tests/Phactory/Sql/PhactoryTest.php
use Phactory\Sql\Phactory;
...
$this->pdo = new \PDO("sqlite:test.db");
$this->phactory = new Phactory($this->pdo);
$this->phactory->define('user');
$this->phactory->reset();
I don't know when it has been changed.
Too late anyways...
The current version, 0.3.2, is not backward compatible with the static method structure that is documented.
Here is the breaking commit: https://github.com/chriskite/phactory/commit/d3b60eeedea955ab7b5803ec29446d19888d3849
Unfortunately, the documentation has not been updated on http://phactory.org and the pearhub repo is no longer available.
I would look to the tests for examples: https://github.com/chriskite/phactory/blob/next/tests/Phactory/Sql/PhactoryTest.php

Resources