Symfony hangs after using Doctrine - php

I am trying to debug something so I made this test controller:
/**
* #Route("/test")
*/
public function reventarAction()
{
$a = $this->getDoctrine()
->getRepository(MyTable::class)
->find(1);
var_dump($a->getId());
die();
}
This works just fine. The ID gets dumped.
However, when I try to debug something else such as the object itself:
var_dump($a);
It loads forever presumably in some sort of recursive loop to the point where my computer freezes.
Any help debugging from Doctrine?

Related

PHPUnit and Guard Clause, not 100% coverage

I have this Guard:
protected function validateRemove($key)
{
if (!isset($this->collection[$key])) {
throw new CategoryCollectionBadItemException();
}
}
And the test:
/**
* #test
* #expectedException InfluenceDecision\Domain\Exception\Category\CategoryCollectionBadItemException
*/
public function removeMethodMustThrowExceptionWithInvalidKey()
{
$this->categoryCollection->add(
new Category(
null,
'test category'
)
);
$this->categoryCollection->remove(1);
}
CategoryCollection remove method calls validateRemove method
The test works fine, but the coverage isn't 100% because the test can't access to the last line of validateRemove method:
What's the propper solution?
That's happening because you are not testing both the branches of the function, in your test case the function breaks when you throw the exception so it's not technically finishing. You have tested half of the function, even if it's the only logic in there.
If you want the 100% coverage, you need to create a test where $this->collection[$key] is set .
In that case, I would suggest to change your function to something like
protected function validateRemove($key)
{
if (!isset($this->collection[$key])) {
throw new CategoryCollectionBadItemException();
}
return true;
}
and then create another test that asserts true when you call validateRemove() and $this->collection[$key] is set.
Mine is an example as I don't really know how do you use that piece of code!

PHPUnit Test result type or also the result variables

during unit testing i'm always get confused about what to test.
Do i need to test the API and only the API or also the method result values.
class SomeEventHandler
{
public function onDispatch (Event $event)
{
if ($event->hasFoo)
{
$model = $this->createResponseModel('foo');
}
else
{
$model = $this->createResponseModel('bar');
}
// End.
return $model;
}
private function createResponseModel ($foo)
{
$vars = array(
'someVare' => true,
'foo' => $foo
);
// End.
return new ResponseModel($vars);
}
}
So should i test if the method onDispatch returns a instance of ResponseModel or should i also test if the variable foo is set properly?
Or is the test below just fine?
class SomeEventHandlerTest
{
// assume that a instance of SomeEventHandler is created
private $someEventHandler;
public function testOnDispatch_EventHasFoo_ReturnsResponseModel ()
{
$e = new Event();
$e->hasFoo = true;
$result = $someEventHandler->onDispatch($e);
$this->assertInstanceOf('ResponseModel', $result);
}
public function testOnDispatch_EventHasNoFoo_ReturnsResponseModel ()
{
$e = new Event();
$e->hasFoo = false;
$result = $someEventHandler->onDispatch($e);
$this->assertInstanceOf('ResponseModel', $result);
}
}
If you were checking the code by hand what is it that you would check? Just that a ResponseModel was returned or that it also had the proper values?
If you weren't writing tests and executed the code what would you look for to ensure that the code was doing what it was supposed to. You would check that the values in the returned object were correct. I would do that by using the public API of the object and verify that the values are right.
One idea is to have the tests such that if the code were deleted, you would be able to recreate all the functionality via only having the tests. Only checking the returned object could result in a function that just has return new ResponseModel();. This would pass the test but would not be what you want.
In short, what you decide to test is subjective, however you should at the minimum test all your public methods.
Many people limit their tests to public methods and simply ensure code coverage on the protected/private methods is adequate. However, feel free to test anything you think warrants a test. Generally speaking, the more tests the better.
In my opinion you should certainly test for your response data, not just the return type.
I rely on Unit Tests to let me make code changes in the future and be satisfied my changes have not created any breaks, just by running the tests.
So in your case, if the "foo" or "bar" response data is important, you should test it.
That way if you later change the response strings by accident, your tests will tell you.

Build a UnitTest with multiple options on the same mocked-method

I have a problem to test a Method like that
public function index(){
if($this->request->is('get')){
if($this->Session->check('saveConflict')){
$this->set('conflict',true);
}else{
$this->set('data','test');
}
if($this->Session->check('full')){
$this->set('data',$this->Model->find('all'));
}else{
$this->set('data','test');
}
}else{
throw new BadRequestException;
}
}
unless that method maybe doesn't make sense, here is my problem. I have to call the method "check" on the Session-Component twice. But I want that for example the first methode mock-call retruns a "false" and the second a "true".
Here's what I have
$this->Editors->Session
->expects($this->once())
->method('check')
->will($this->returnValue(true));
I've tried it with the expectation "$this->at(1)" the call via order-index. But i think that isnt pretty clever because if I add a Session->check anywhere in the interpreted way though my base-method for example i have to change all those test-lines to make it work properly again.
I use CakePHP 2.4.6 and php-unit 4.1.3.
Is there any other why to do what I want to do?
Use the
->will($this->onConsecutiveCalls(array('return_value1',
'retur_value2',
...)));
Give the sequence of the return value in the order you want, the mocked method will return it in order.Or you can try the $this->returnCallback to do some sophisticated customize.You can find the example here How can I get PHPUnit MockObjects to return differernt values based on a parameter?.
Example
If you just want to do the unit test and cover all the path,I'll do like this:
public function testIndex()
{
....
$this->Editors->Session
->expects($this->any())
->method('check')
->will($this->returnCallback(array($this,'sessionCallback')));
$this->object->index();
$this->object->index();
.....
}
private $sessionFlag;
public function sessionCallback($value)
{
$rtnValue = $this->sessionFlag[$value];
$this->sessionFlag[$value] = (!$rtnValue);
return $rtnValue;
}

Could you post examples on how to use PHPUnit with NetBeans?

I'm new to PHPUnit and I want to use it with Netbeans. I'm already aware that there is documentation for PHPUnit on it's own but there isn't much documentation on how to use it with Netbeans. It would be great to see some working examples first. I learn better that way.
So from the Netbeans site they give this example and then you would Right Click File->Create PHPUnit Tests to automatically generate PHPUnit classes:
class Calculator{
/**
* #assert (0,0) == 0
* #assert (0,1) == 1
* #assert (1,0) == 1
* #assert (1,1) == 2
* #assert (1,2) == 4
*/
public function add($a, $b){
return $a + $b;
}
}
However, im reading another PHP book and in it they do it this way
class Session {
public function __construct($one, $two){}
public function login(){}
public function isLoggedIn() {return null;}
}
require_once("PHPUnit/Autoload.php");
class TestSession extends PHPUnit_Framework_TestCase {
private $_session;
function setUp() {
$dsn = array(
'phptype' => "pgsql",
'hostspec' => "localhost",
'database' => "widgetworld",
'username' => "wuser",
'password' => "foobar"
);
$this->_session = new Session($dsn, true);
}
function testValidLogin() {
$this->_session->login("ed", "12345");
$this->assertEquals(true, $this->_session->isLoggedIn());
}
function testInvalidLogin() {
$this->_session->login("ed", "54321"); // fail
$this->assertEquals(false, $this->_session->isLoggedIn());
}
}
$suite = new PHPUnit_Framework_TestSuite;
$suite->addTest(new TestSession("testValidLogin"));
$suite->addTest(new TestSession("testInvalidLogin"));
$testRunner = new PHPUnit_TextUI_TestRunner();
$testRunner->run( $suite );
Could you help me understand how to do PHPUnit tests in Netbeans by converting the above example? Thanks
I don't know but would doing something like this in Netbeans be correct?:
class Session {
public function __construct($one, $two) {}
public function login() {
/**
* #assert ("ed", "12345")->isLoggedIn() == true
*/
/**
* #assert ("ed", "54321")->isLoggedIn() == false
*/
}
public function isLoggedIn() {return null;}
}
I have never use #assert in NetBeans, but it looks like they simply inform the test case generator how to write the tests. In the end, NetBeans creates a test case for the class which will look similar to TestSession above (though it would be called SessionTest).
If you use #assert to define your test data, keep in mind that you'll need to regenerate the test every time you change them, and this will overwrite any changes you made to the test case after doing so. I would recommend writing the test cases by hand as you can't use #assert as you write it to test the session. It is designed to write tests like "Given parameters X, Y, and Z, the return value should be R." You can't use it to test side effects of your methods.
To do PHPUnit testing in Netbeans, do the following things.
Go to "File" > "Project properties" from the main men
Then select click on "PHPUnit" tab on vertical menu on the left of the dialog window
Choose the option how you will run PHPUnit such as using bootstrap file or XML or custom suites
Then, go to "Run" > "Test Project" from the main menu
Then, you will prompted for selecting where are the test files
Then, you will also prompted for where is your PHPUnit shell script or bat file(on Windows) on your computer if you haven't configured it for Netbeans
Once you setup properly like above, every time you need to run test cases, going to "Run" > "Test Project" from the menu

How do I write unit tests in PHP? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I've read everywhere about how great they are, but for some reason I can't seem to figure out how exactly I'm supposed to test something. Could someone perhaps post a piece of example code and how they would test it? If it's not too much trouble :)
There is a 3rd "framework", which is by far easier to learn - even easier than SimpleTest, it's called phpt.
A primer can be found here:
http://qa.php.net/write-test.php
Edit: Just saw your request for sample code.
Let's assume you have the following function in a file called lib.php:
<?php
function foo($bar)
{
return $bar;
}
?>
Really simple and straight forward, the parameter you pass in, is returned. So let's look at a test for this function, we'll call the test file foo.phpt:
--TEST--
foo() function - A basic test to see if it works. :)
--FILE--
<?php
include 'lib.php'; // might need to adjust path if not in the same dir
$bar = 'Hello World';
var_dump(foo($bar));
?>
--EXPECT--
string(11) "Hello World"
In a nutshell, we provide the parameter $bar with value "Hello World" and we var_dump() the response of the function call to foo().
To run this test, use: pear run-test path/to/foo.phpt
This requires a working install of PEAR on your system, which is pretty common in most circumstances. If you need to install it, I recommend to install the latest version available. In case you need help to set it up, feel free to ask (but provide OS, etc.).
There are two frameworks you can use for unit testing. Simpletest and PHPUnit, which I prefer. Read the tutorials on how to write and run tests on the homepage of PHPUnit. It is quite easy and well described.
You can make unit testing more effective by changing your coding style to accommodate it.
I recommend browsing the Google Testing Blog, in particular the post on Writing Testable Code.
I rolled my own because i didnt have time to learn someone elses way of doing things, this took about 20 minutes to write up, 10 to adapt it for posting here.
Unittesting is very usefull to me.
this is kinda long but it explains itself and there is an example at the bottom.
/**
* Provides Assertions
**/
class Assert
{
public static function AreEqual( $a, $b )
{
if ( $a != $b )
{
throw new Exception( 'Subjects are not equal.' );
}
}
}
/**
* Provides a loggable entity with information on a test and how it executed
**/
class TestResult
{
protected $_testableInstance = null;
protected $_isSuccess = false;
public function getSuccess()
{
return $this->_isSuccess;
}
protected $_output = '';
public function getOutput()
{
return $_output;
}
public function setOutput( $value )
{
$_output = $value;
}
protected $_test = null;
public function getTest()
{
return $this->_test;
}
public function getName()
{
return $this->_test->getName();
}
public function getComment()
{
return $this->ParseComment( $this->_test->getDocComment() );
}
private function ParseComment( $comment )
{
$lines = explode( "\n", $comment );
for( $i = 0; $i < count( $lines ); $i ++ )
{
$lines[$i] = trim( $lines[ $i ] );
}
return implode( "\n", $lines );
}
protected $_exception = null;
public function getException()
{
return $this->_exception;
}
static public function CreateFailure( Testable $object, ReflectionMethod $test, Exception $exception )
{
$result = new self();
$result->_isSuccess = false;
$result->testableInstance = $object;
$result->_test = $test;
$result->_exception = $exception;
return $result;
}
static public function CreateSuccess( Testable $object, ReflectionMethod $test )
{
$result = new self();
$result->_isSuccess = true;
$result->testableInstance = $object;
$result->_test = $test;
return $result;
}
}
/**
* Provides a base class to derive tests from
**/
abstract class Testable
{
protected $test_log = array();
/**
* Logs the result of a test. keeps track of results for later inspection, Overridable to log elsewhere.
**/
protected function Log( TestResult $result )
{
$this->test_log[] = $result;
printf( "Test: %s was a %s %s\n"
,$result->getName()
,$result->getSuccess() ? 'success' : 'failure'
,$result->getSuccess() ? '' : sprintf( "\n%s (lines:%d-%d; file:%s)"
,$result->getComment()
,$result->getTest()->getStartLine()
,$result->getTest()->getEndLine()
,$result->getTest()->getFileName()
)
);
}
final public function RunTests()
{
$class = new ReflectionClass( $this );
foreach( $class->GetMethods() as $method )
{
$methodname = $method->getName();
if ( strlen( $methodname ) > 4 && substr( $methodname, 0, 4 ) == 'Test' )
{
ob_start();
try
{
$this->$methodname();
$result = TestResult::CreateSuccess( $this, $method );
}
catch( Exception $ex )
{
$result = TestResult::CreateFailure( $this, $method, $ex );
}
$output = ob_get_clean();
$result->setOutput( $output );
$this->Log( $result );
}
}
}
}
/**
* a simple Test suite with two tests
**/
class MyTest extends Testable
{
/**
* This test is designed to fail
**/
public function TestOne()
{
Assert::AreEqual( 1, 2 );
}
/**
* This test is designed to succeed
**/
public function TestTwo()
{
Assert::AreEqual( 1, 1 );
}
}
// this is how to use it.
$test = new MyTest();
$test->RunTests();
This outputs:
Test: TestOne was a failure
/**
* This test is designed to fail
**/ (lines:149-152; file:/Users/kris/Desktop/Testable.php)
Test: TestTwo was a success
Get PHPUnit. It is very easy to use.
Then start with very simple assertions. You can do alot with AssertEquals before you get into anything else. That's a good way to get your feet wet.
You may also want to try writing your test first (since you gave your question the TDD tag) and then write your code. If you haven't done this before it is an eye-opener.
require_once 'ClassYouWantToTest';
require_once 'PHPUnit...blah,blah,whatever';
class ClassYouWantToTest extends PHPUnit...blah,blah,whatever
{
private $ClassYouWantToTest;
protected function setUp ()
{
parent::setUp();
$this->ClassYouWantToTest = new ClassYouWantToTest(/* parameters */);
}
protected function tearDown ()
{
$this->ClassYouWantToTest = null;
parent::tearDown();
}
public function __construct ()
{
// not really needed
}
/**
* Tests ClassYouWantToTest->methodFoo()
*/
public function testMethodFoo ()
{
$this->assertEquals(
$this->ClassYouWantToTest->methodFoo('putValueOfParamHere), 'expectedOutputHere);
/**
* Tests ClassYouWantToTest->methodBar()
*/
public function testMethodFoo ()
{
$this->assertEquals(
$this->ClassYouWantToTest->methodBar('putValueOfParamHere), 'expectedOutputHere);
}
For simple tests AND documentation, php-doctest is quite nice and it's a really easy way to get started since you don't have to open a separate file. Imagine the function below:
/**
* Sums 2 numbers
* <code>
* //doctest: add
* echo add(5,2);
* //expects:
* 7
* </code>
*/
function add($a,$b){
return $a + $b;
}
If you now run this file through phpdt (command-line runner of php-doctest) 1 test will be run. The doctest is contained inside the < code > block. Doctest originated in python and is fine for giving useful & runnable examples on how the code is supposed to work. You can't use it exclusively because the code itself would litter up with test cases but I've found that it's useful alongside a more formal tdd library - i use phpunit.
This 1st answer here sums it up nicely (it's not unit vs doctest ).
phpunit is pretty much the defacto unit testing framework for php. there is also DocTest (available as a PEAR package) and a few others.
php itself is tested for regressions and the like via phpt tests which can also be run via pear.
Codeception tests are much like common unit tests but are much powerful in things where you need mocking and stubbing.
Here is the sample controller test. Notice how easily stubs are created. How easily you check the method was invoked.
<?php
use Codeception\Util\Stub as Stub;
const VALID_USER_ID = 1;
const INVALID_USER_ID = 0;
class UserControllerCest {
public $class = 'UserController';
public function show(CodeGuy $I) {
// prepare environment
$I->haveFakeClass($controller = Stub::makeEmptyExcept($this->class, 'show'));
$I->haveFakeClass($db = Stub::make('DbConnector', array('find' => function($id) { return $id == VALID_USER_ID ? new User() : null ))); };
$I->setProperty($controller, 'db', $db);
$I->executeTestedMethodOn($controller, VALID_USER_ID)
->seeResultEquals(true)
->seeMethodInvoked($controller, 'render');
$I->expect('it will render 404 page for non existent user')
->executeTestedMethodOn($controller, INVALID_USER_ID)
->seeResultNotEquals(true)
->seeMethodInvoked($controller, 'render404','User not found')
->seeMethodNotInvoked($controller, 'render');
}
}
Also there are other cool things. You can test database state, filesystem, etc.
Besides the excellent suggestions about test frameworks already given, are you building your application with one of the PHP web frameworks that has automated testing built in, such as Symfony or CakePHP? Sometimes having a place to just drop in your test methods reduces the start-up friction some people associate with automated testing and TDD.
Way too much to re-post here, but here is a great article on using phpt. It covers a number of aspects around phpt that are often overlooked, so it could be worth a read to expand your knowledge of php beyond just writing a test. Fortunately the article also discusses writing tests!
The main points of discussion
Discover how marginally documented aspects of PHP work (or pretty much any part for that matter)
Write simple unit tests for your own PHP code
Write tests as part of an extension or to convey a potential bug to the internals or QA groups
I know there is a lot of info here already, but since this still shows up on Google searches i might as well add Chinook Test Suite to the list. It is a simple and small test framework.
You can easily test your classes with it and also create mock objects. You run the tests through a web browser and (not yet) through a console.
In the browser you can specify what test class or even what test method to run. Or you can simply run all tests.
A screenshot from the github page:
What i like about it is the way you assert tests. This is done with so called "fluent assertions". Example:
$this->Assert($datetime)->Should()->BeAfter($someDatetime);
And creating mock objects is a breeze too (with a fluent like syntax):
$mock = new CFMock::Create(new DummyClass());
$mock->ACallTo('SomeMethod')->Returns('some value');
Anyway, more info can be found on the github page with a code example as well:
https://github.com/w00/Chinook-TestSuite

Categories