I like to have empty functions on occasion for placeholders (primarily empty constructors, since it helps avoid accidental duplication of constructors since my team knows there must always be one somewhere).
I also like to have at least one test for every method of a class (largely because it is a nice easy rule to hold my team against).
My question is simple: what should we put in these empty test methods to prevent the "no tests" warning.
We could just do $this->assertTrue(true), which I know will work just fine. However, I was wondering if there was anything a touch more official and proper (preferably something which makes it so the method isn't counted in the number of tests run, artificially inflating it a bit).
Thanks.
try this :
/**
* #covers Controllers\AdminController::authenticate
* #todo Implement testAuthenticate().
*/
public function testAuthenticate()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
You try a reflection class on the function and ensure that the method is there. Then the test could simply be that the method exists (empty or not), which will pass without a warning.
class MethodExistsTest extends \PHPUnit_Framework_TestCase
{
protected $FOO;
protected function setUp()
{
$this->FOO = new \FOO();
}
/**
* #covers \FOO::Bar
*/
public function testEmptyMethodBarExists()
{
$ReflectionObject = new \ReflectionObject($this->FOO);
$this->assertTrue($ReflectionObject->getMethod('Bar'));
}
/**
* #covers \FOO::__construct
*/
public function testConstructorExists()
{
$ReflectionObject = new \ReflectionObject($this->FOO);
$this->assertNotNull($ReflectionObject->getConstructor());
}
}
Related
We use PHPUnit filtering quite extensively and it appears that it doesn't prevent us from executing setUpBeforeClass() and tearDownAfterClass() in test classes that don't match the filtered results.
For those unaware, you can use the --filter option to filter your PHPUnit tests.
Other testing frameworks like mocha don't execute fixtures unless they match the filter.
I want to start by saying that I have great respect for all the phpunit contributors.
Our workaround was to develop a new base class that provides a new set of constructs that can be used instead of setUpBeforeClass() and tearDownAfterClass().
class Test extends PHPUnit_Framework_TestCase {
/**
* PHPUnit has a serious design flaw where setUpBeforeClass() and tearDownAfterClass() are still
* executed for all test classes even if they don't match the filter. This appears to be due to
* PHPUnit applying the filter after these fixtures. Fortunately, with a little magic, we can
* define constructs for before() and after() that achieve our desired behavior. Some may say that
* this is not a PHPUnit bug, but other testing frameworks like mocha don't execute any of the
* fixtures unless the filters match.
*/
/**
* #var boolean True if we are executing this test
*/
protected static $executing = false;
/**
* Use instead of setUpBeforeClass() to create a fixture that is called once per test class and
* not called unless it is in the filter results.
*/
public static function before() {}
/**
* Use instead of tearDownAfterClass() to create a fixture that is called once per test class and
* not called unless it is in the filter results.
*/
public static function after() {}
/**
* A base method for setUp() that uses the $executing flag to determine whether or not to run
* before(). We cannot use setUpBeforeClass() here as setUpBeforeClass() will run before any
* filters are applied.
*/
protected function setUp() {
if (!self::$executing) {
static::$executing = true;
static::before();
}
}
/**
* A base method for tearDownAfterClass() that uses the $executing flag to determine whether or
* not to run after()
*/
public static function tearDownAfterClass() {
if (static::$executing) {
// Set to false so that this doesn't trigger execution of another classes fixtures as $executing
// is a static member
static::$executing = false;
static::after();
}
}
}
you can then use the new before() and after() constructs like so and they will not be executed if the test is not part of the filtered results:
class MyTest extends Test {
public static function before() {
// Code done once before all tests
}
public function testFoo() {
// Test something
}
public static function after() {
// Code done once after all tests
}
}
I know it's possible to test private/protected methods with PHPUnit using reflection or other workarounds.
But most sources tell me that it's not best practice to write tests for private methods inside of a class.
You are supposed to test the class as if it were a "black box" — you just test for expected behavior by comparing inputs with outputs disregarding the internal mechanics. Writing tests for classes should also notify you to unused private methods, by showing lack of code coverage.
When I test my class and generate an HTML report, it shows the private methods as not covered by tests, even though the lines from which they are called are absolutely executed/covered. I know that the private methods are executed, because if they weren't the assertions on my class would not pass.
Is this expected behavior in PHPUnit? Can I strive for 100% coverage, while still testing private methods only indirectly?
Some simplified example code (using RestBundle in Symfony2):
class ApiController extends FOSRestController {
/*
* #REST\View()
* #REST\Get("/api/{codes}")
*/
public function getCodesAction($codes) {
$view = new View();
$view->setHeader('Access-Control-Allow-Origin', '*');
$view->setData(array('type' => 'codes','data' => $this->_stringToArray($codes)));
$view->setFormat('json')->setHeader('Content-Type', 'application/json');
return $this->handleView($view);
}
private function _stringToArray($string){
return explode('+',$string);
}
The public function shows as "covered", the private function is indirectly covered but shows colored red in PHPUnit reports.
Test:
class ApiControllerTest extends WebTestCase {
public function test_getCodesAction(){
$client = static::createClient();
$client->request('GET', '/api/1+2+3');
$this->assertContains('{"type": "codes", "data": [1,2,3]}', $client->getResponse()->getContent());
}
}
This is just a silly example of course, I could just as well include the explode() right there in the public function; But the controllers I'm writing tests for contain much more intricate and re-usable private functions which transform data in more complex ways (but are still side-effect free).
In Phpunit you can specify the Covered Methods with special annotation, as descrived in the doc.
You can do something like this:
class ApiControllerTest extends WebTestCase {
/**
* #covers ApiController::getCodesAction
* #covers ApiController::_stringToArray
*/
public function test_getCodesAction(){
$client = static::createClient();
$client->request('GET', '/api/1+2+3');
$this->assertContains('{"type": "codes", "data": [1,2,3]}', $client->getResponse()->getContent());
}
}
Hope this help
When mocking an interface in PHPUnit, PhpStorm complains when it's used as parameter for a type-hinted function.
Example
interface InterfaceA{
}
class ClassA{
public function foo(InterfaceA $foo){}
}
class PhpStormTest extends PHPUnit_Framework_TestCase
{
public function testFoo(){
$mock = $this->getMock("InterfaceA");
$a = new ClassA();
$a->foo($mock);
}
}
On $a->foo($mock); PhpStorm underlines $mock with the warning Expected InterfaceA, got PHPUnit_Framework_MockObject_MockObject
Image
I guess it's happening because PHPUnit creates the mock a runtime and PhpStorm cannot know that it's actually implementing the interface.
I found a workaround to this problem in the Jetbrain blog at PhpStorm Type Inference and Mocking Frameworks. The important part:
By default, PhpStorm is capable of figuring out the available methods
on the mock object. However, it only displays those for PHPUnit’s
PHPUnit_Framework_MockObject_MockObject class. Fortunately, we can
solve this by instructing PhpStorm to infer type information from
other classes as well, by using a simple docblock comment.
So to make the warning disappear, we need to add /** #var InterfaceA */ /** #var InterfaceA|PHPUnit_Framework_MockObject_MockObject */ (cudos to Supericy) to let PhpStorm know our mock actually implements InterfaceA:
interface InterfaceA{
}
class ClassA{
public function foo(InterfaceA $foo){}
}
class PhpStormTest extends PHPUnit_Framework_TestCase
{
public function testFoo(){
/** #var InterfaceA|PHPUnit_Framework_MockObject_MockObject */
$mock = $this->getMock("InterfaceA");
$a = new ClassA();
$a->foo($mock);
}
}
This bugged me for some time, hope it helps someone :)
Edit
Since PHPUnit_Framework_MockObject_MockObject is really ugly to type, you can abbreviate it via MOOMOO and let PHPStorms auto-complete do the rest:
Another plugin I have used for this is the Dynamic Return Type Plugin, it lets you configure return types of methods in a very dynamic way (the example is to have better type information from Mocks).
Another, less verbose but possibly riskier, approach can be to wrap the call to getMock() with your own function and mark that with #return mixed:
/**
*
* #return mixed
*/
public function myGetMock($str)
{
return $this->getMock($str);
}
Calling this method instead of $this->getMock() will make the warning disappear.
consider the following code as PHP-style pseudo code to get my point across.
class C extends PHPUnit_Framework_TestCase
{
public function m1()
{
$v = $this->m2();
if($v == "x")
{
throw new Exception();
}
}
protected function m2()
{
[...];
return $v;
}
}
now I want to add a test that asserts that an Exception is thrown if m2() returns "x".
How can I simulate that?
I thought about using Reflection to redefine the method during runtime, but it seems that Reflection doesn't offer such a functionality and I would have to resort to experimental extensions like classkit or runkit. Would that be the way to go?
In this case I could extend the class and redefine m2() but where would I put that derived class then? In the same file as the test?
The latter solution wouldn't work anymore if I would choose m2 to be private.
I'm quite sure that there is a best practice to deal with this situation.
Ether I'm completely off on what you are trying to do here or you are doing something that confuses me greatly.
To me is seems that you are asking for is that you want to check that your test method throws an exception.
class C extends PHPUnit_Framework_TestCase
Why would you want to test your test method?
I'm going to assume that that is the real class and not your test
In that case I always strongly argue for just testing it as if the protected method would be inline in the public method.
You want to test the external behavior of your class. Not the implementation. The protected method is and implementation detail that your test shouldn't care about. That would mean that you would have to change your test when you change that protected method.
And from there on out:
class CTest extends PHPUnit_Framework_TestCase {
public function testM1NormalBehavior() {
}
/**
* #expectedException YourException
*/
public function testM1ThrowsExceptionWhenM2ConditionsAreMet() {
$c = new C('set_Up_In_A_Way_That_Makes_M2_Return_X');
$c->m1();
}
}
You can use a partial mock of C to force m2() to return "x". I'll assume that the extends PHPUnit_Framework_TestCase was accidental and that C is actually the class under test and not the unit test itself.
class CTest extends PHPUnit_Framework_TestCase {
/**
* #expectedException Exception
*/
function testM1ThrowsExceptionWhenM2ReturnsX() {
$c = $this->getMock('C', array('m2'));
$c->expects($this->once())->method('m2')->will($this->returnValue('x'));
$c->m1();
}
}
Maybe I missed out on a detail, but I wrote a small test case for a singleton _clone method yet it is not showing up as tested in the code coverage report.
/**
* #covers ErrorHandling::__clone
*/
public function test__cloneNotCloneable(){
$class = new ReflectionClass('ErrorHandling');
$method = $class->getMethod('__clone');
self::assertTrue($method->isFinal(), '__clone method is not final.');
self::assertTrue($method->isPrivate(), '__clone method is not private.');
}
The __clone method is the usual private/final __clone() of a regular (evil) singleton.
/**
* Define __clone as final and private to dissallow cloning.
*/
private final function __clone(){}
I know it's probably overkill testing for this, but the code-coverage report is sort of the graphical representation of a job 'well done'. Is there a way to have this method marked as covered in the code coverage report?
The #covers tag tells PHPUnit that you intend to test the named method; it does not mark the method as having been tested. Since you cannot call the method, Xdebug won't tell PHPUnit that its code has been executed, and it will never be covered in your report.
Your best bet is to tell PHPUnit to ignore the method in the report by using the #codeCoverageIgnore docblock tag.
/**
* Define __clone as final and private to dissallow cloning.
*
* #codeCoverageIgnore
*/
private final function __clone() { }
You can ignore any range of lines by enclosing them in a pair of one-line start/stop comments.
// #codeCoverageIgnoreStart
private final function __clone() { }
// #codeCoverageIgnoreEnd
Finally, you can ignore a single line by adding a one-line comment to it.
private final function __clone() { } // #codeCoverageIgnore