I have a problem testing traits. One of my classes uses a trait and implements an interface. Interface methods by the way are being implemented by a trait.
When I run phpunit with coverage report enabled I see that my class is shown as 100% covered, interface is shown as 100% covered, by trait is shown as 0%:
The class uses trait, methods from trait are being called in test suite, but still trait is considered uncovered.
Should traits be tested separately somehow? I know about getMockForTrait() method, but I would like to avoid it. Is there any way to fix the issue and to cover trait by testing the class itself?
Related
Stupid question... In the Symfony docs, unit test classes extend \PHPUnit_Framework_TestCase but in PHPUnit docs, test classes extend PHPUnit\Framework\TestCase. Is there a difference, are they the same, or am I missing a subtle PHP feature where _ is equivalent to \?
Short of actually testing it out myself, can I use either, or just one in Symfony?
Update: It's been helpfully explained to me that these two classes are just a difference between PHPUnit versions. After my own research and for the record, Symfony 3.1 still extends \PHPUnit_Framework_TestCase in its own KernelTestCase class that powers Symfony's functional testing. To avoid breaking code, I'm going to play safe & extend WebTestCase that inherits from \PHPUnit_Framework_TestCase when unit testing with Symfony specifically. Such unit tests still work with PHPUnit 5.6 anyway
These are the same but since PHPUnit 5.4 it's recommended to use TestCase. However, it's not a problem if you stay with PHPUnit_Framework_TestCase.
See a very similar question: PHPUnit can't found the "TestCase" class
I've been working on modifying/converting the Recurly PHP client library to work in Laravel 5.1.
I got namespacing to work to the point that I can reference the Recurly library classes appropriately, but have run into the wall of interfaces that those classes implement causing the classes to fail out.
As a note: these interfaces are base php interfaces, but I can't figure out how to get Laravel 5.1 to let a class implement a base php interface that isn't a 'baked-in' Laravel interface.
System PHP version: 5.6.22
Example Class declaration causing issues:
<?php
namespace App\Libraries\Recurly;
class Recurly_CurrencyList implements ArrayAccess, Countable, IteratorAggregate
{
This is the error message that gets thrown:
Interface 'App\Libraries\Recurly\ArrayAccess' not found
I am trying to test a class that implements an interface that is defined outside the scope of the classes package (i.e. I pull it in as a dependency using composer during integration).
I would like to test this concrete class without having to pull in the interface it depends on. Is there anyway to test this in php unit test?
At the moment I can't even instantiate an instance as the interface is obviously not found.
The interface that your class is not a dependency in that sense... There is nothing to mock. You just need to make sure that the class is an instance of the interface in your tests for that class.
You need to change something about your testing environment so that the interface is available in order to test your class. So that you can instantiate and test the behavior of the methods that the interface specifies.
Dependency injection is about objects that your code NEEDS not what your code is. An interface or an abstract class are not dependencies. Even though your code "depends" on those things existing.
Dependencies are external objects that you class needs to do something. Interfaces and abstract classes define what are you class is.
This question: Run PHPUnit Tests in Certain Order has an accepted answer which I agree with, but the design problem is with PHP and PHPUnit.
The project I'm testing uses ZF2 and Doctrine. The AbstractHttpControllerTestCase has a method "dispatch" which instantiates a ZF2 Application and goes through all the steps of creating the Response object. These tests are annotated with #covers to ensure other methods aren't covered by running requests during a test. The requests may involve view scripts which invoke view helpers which use all sorts of services, so it becomes infeasible to mock all services used during a given request (and this code would become tedious to copy and maintain for each test).
PHPUnit has the ability to run tests in a separate process, it does this by forking a new PHP instance and feeding it compiled code templates (weird stuff). It will then include all files listed by get_included_files(), which includes everything that ever hit the autoloader. Even with preserveGlobalState disabled, it will still include everything that's been touched by all prior tests in the new process.
Some of the dependencies (installed through composer) use static methods, classes marked final or both. Static methods can be mocked by PHPUnit, final classes have to be overloaded using Mockery as PHPUnit will flat out refuse to create mock objects of final classes. Overloading classes and functions (using the namespace trick) must be done in separate processes as to not influence subsequent tests. So far, so good.
Enter a test which overloads a dependency to set expectations on static methods (on a class which may or may not be marked final), or to set expectations on objects which are not yet instantiated. This will only work if none of the prior tests have ever touched the class to overload and set expectations on, or it'll fail with a "cannot redeclare class" error. PHPUnit has tried to be helpful and included everything to recreate the test environment in the subprocess, but as a result ruins the test case.
Therefore, it would be incredibly useful to mark tests with e.g. "#group isolated" and have those tests run before any other tests without having to invoke PHPUnit twice (besides the inconvenience of it, it would ruin coverage analysis).
Alternatively, if there's a way to override a class that already exists in PHP 5.5, that would allow the stricken test case to fix its precondition. But that's probably not going to happen (runkit is not an acceptable answer in any case).
I recently installed the CI_UNIT test environment for my ci application. The preinstalled tests ran as they should but when I tried to test one of my controllers, it crashed at the line
$this->CI = set_controller('...');
of the controller test class without throwing an error. I found out, that it depends on the class from which I inherit the controller. In my current application I have three levels of inheritance.
The built in CI_Controller
A class that extends CI_Controller and which provides functions that are specific for any kind of controller of this application: The APP_Controller.
Some classes that extend the APP_Controller and where one of these, in this case provides functions only interesting for the REST API of the application.
The CI_UNIT however seems to work if and only if the controller directly inherits from CI_Controller. How can I get around this?