PHPUnit 3.7.19 and Symfony2 broken tests - unit-testing

I'm developing some test for a Symfony2.0 project and running them with PHPUnit.
On my PC works fine but trying them in other environments the tests fails. I thought the problem was php version but after run them in differents environments I'm lost.
My environment is Ubuntu 12.04 and PHP 5.3.10 => Works fine.
2 PC with Ubuntu 12.10 and PHP 5.4.6:
Fatal error: Call to a member function get() on a non-object
This error is on a class which extends Symfony\Bundle\FrameworkBundle\Test\WebTestCase where is overwritten the setUp() and tearDown() methods.
public function setUp()
{
$this->client = static::createClient();
$this->client->followRedirects(true);
$crawler = $this->client->request('GET', '/admin/login');
$loginForm = $crawler->selectButton('save')->form(array(
'_username' => 'user',
'_password' => 'pass'
));
$this->client->submit($loginForm);
$this->container = $this->client->getContainer();
parent::setUp();
}
public function tearDown()
{
//Here is get() on a non-object, $this->container doesn't exists
$this->container->get('doctrine.odm.mongodb.document_manager')->getConnection()->close();
parent::tearDown();
}
2 PC, one with Ubuntu 12.10 and PHP 5.4.6 and other with Windows 7 and PHP 5.3.8:
PHP Fatal error: Call to a member function getSite() on a non-object
This error is on a class which extends the above class that has tearDown() method wrong but in this case this class works and the error is different although is related with $this->container:
//In this case, the user doesn't exists
$site = $this->container->get('security.context')
->getToken()->getUser()->getSite();
The problem is I don't know why is this. If this is related to PHP, PHPUnit(All of us have the same version), Symfony2.0 or SO.
Edit:
Ok, problems solved.
First:
Fatal error: Call to a member function get() on a non-object
Had a wrong line of code in the class which has setUp() and tearDown() methods. A line like that:
$link = $crawler->filter('a:contains("Test")')->eq(1)->link();
I had this line commented, sorry :). But I don't know why PHPUnit show me this error and not the error of link method.
Second:
PHP Fatal error: Call to a member function getSite() on a non-object
In the others environments, the test database had not been deployed.
This question will not help anyone but help me to try new things. Thanks!

It is an exected behavior for PHPUnit.
I managed to reproduce the error with the following code:
final class ExceptionErrorTest extends PHPUnit_Framework_TestCase
{
/**
* #var MyObject
*/
private $object;
public function setUp() {
throw new \RuntimeException();
$this->object = new MyObject();
}
public function testItShouldNeverBeCalled()
{
var_dump('never called');
}
public function tearDown()
{
$this->object->neverCalled();
}
}
class MyObject
{
public function neverCalled() {
return true;
}
}
// will ouput PHP Fatal error:
Call to a member function neverCalled() on a non-object in ExceptionErrorTest.php on line 22
To explain more clearly, PHPUnit will catch any exceptions triggered in the setUp method (in order for the printers to show at the end of the execution).
After that you can see that the tearDown() is called to finish the test, but since the initialization of the attribute was never reached, a PHP error is issued, and PHPUnit will never reach the code where it shows all the exceptions that occurred.
That is why you did not get the exception. To fix this, you need to make sure that any code that can throw exceptions in the setup is wrapped in a try() catch () statement like this:
public function setUp() {
try {
throw new \RuntimeException('My message');
} catch (\Exception $e) {
echo 'An error occured in the setup: ' $e->getMessage();
die;
}
$this->object = new MyObject();
}
Hope it helps someone in the future.

Related

How to get get page source in codeception yii 2

I need save the source code of failed test to fix it. How to get the source html while using codeception test in yii 2?
I cannot get $I->grabPageSource() and $I->_getResponseContent() to work though there are these exact functions.
public function checkCall(FunctionalTester $I)
{
$I->amOnRoute('mx/ed',['model' => 'State']);
$I->seeResponseCodeIs(200);
$I->seeResponseCodeIsSuccessful();
$html = $I->grabPageSource();
}
Codeception saves page source of last request for all failed tests in tests/_output directory by itself, there is nothing for you to do.
Failed assertion throws exception so your code after $I->seeResponseCodeIsSuccessful is not executed.
If you want to implement some custom error handling in specific test, you can wrap assertions in try-catch block and grabPageSource inside catch.
public function checkCall(FunctionalTester $I)
{
$I->amOnRoute('mx/ed',['model' => 'State']);
try{
$I->seeResponseCodeIs(200);
$I->seeResponseCodeIsSuccessful();
} catch (Exception $e) {
$html = $I->grabPageSource();
//do your error handling here
throw $e; //rethrow exception to make test fail
}
}
If you want to implement custom error handling for all tests, add _failed method to Helper\Functional class in tests/_support/Helper directory.
public function _failed(\Codeception\TestInterface $test, $fail)
{
$testName = $test->getMetadata()->getName();
$pageSource = $this->getModule('Yii2')->getPageSource();
//do your error handling here
}

PHPUnit test in Zend Framework 3

I am trying to create a test case on the login action with 2 post parameter the code is as here
namespace UserTest\Controller;
use Application\Controller\LoginController;
use Application\Service\AuthenticationService;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\Parameters;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class UserControllerTest extends AbstractHttpControllerTestCase
public function testIndexActionCanBeAccessed()
{
$p = new Parameters();
$p->set('username','foo');
$p->set('password','bar');
$this->getRequest()->setMethod('POST');
$this->getRequest()->setPost($p);
$this->dispatch('widget/login');
$this->assertModuleName('Application');
$this->assertControllerName(LoginController::class);
$this->assertControllerClass('LoginController');
//$this->assertMatchedRouteName('login');
}
and executing the test case from the command line the command is
./vendor/bin/phpunit
/var/www/myproject/application/module/Application/test/Controller/UserControllerTest.php
and the script throwing error that is
Fatal error: Declaration of Application\Service\AuthenticationService::authenticate() must be compatible with Zend\Authentication\AuthenticationService::authenticate(?Zend\Authentication\Adapter\AdapterInterface $adapter = NULL) in /var/www/myproject/application/module/Application/src/Application/Service/AuthenticationService.php on line 16
Please, help me to fix this issue and let me know what i am doing wrong in it

Issue testing Laravel Controller with Mockery | trying to get property of non-object

I'm very new to testing controllers and I'm running into a problem with a method(). I believe I'm either missing something in my test or my Controller / Repository is designed incorrectly.
The application I'm writing is basically one of those secure "one time" tools. Where you create a note, the system provides you with a URL, once that url is retrieved the note is deleted. I actually have the application written but I am going back to write tests for practice (I know that's backwards).
My Controller:
use OneTimeNote\Repositories\NoteRepositoryInterface as Note;
class NoteController extends \Controller {
protected $note;
public function __construct(Note $note)
{
$this->note = $note;
}
public function getNote($url_id, $key)
{
$note = $this->note->find($url_id, $key);
if (!$note) {
return \Response::json(array('message' => 'Note not found'), 404);
}
$this->note->delete($note->id);
return \Response::json($note);
}
...
I've injected my Note interface in to my controller and all is well.
My Test
use \Mockery as M;
class OneTimeNoteTest extends TestCase {
public function setUp()
{
parent::setUp();
$this->mock = $this->mock('OneTimeNote\Repositories\EloquentNoteRepository');
}
public function mock($class)
{
$mock = M::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
public function testShouldReturnNoteObj()
{
// Should Return Note
$this->mock->shouldReceive('find')->once()->andReturn('test');
$note = $this->call('GET', '/note/1234567890abcdefg/1234567890abcdefg');
$this->assertEquals('test', $note->getContent());
}
}
...
The error I'm getting
1) OneTimeNoteTest::testShouldReturnNoteObj
ErrorException: Trying to get property of non-object
/Users/andrew/laravel/app/OneTimeNote/Controllers/NoteController.php:24
Line 24 is in reference to this line found in my controller:
$this->note->delete($note->id);
Basically my abstracted repository method delete() obviously can't find $note->id because it really doesn't exist in the testing environment. Should I create a Note within the test and try to actually deleting it? Or would that be something that should be a model test? As you can see I need help, thanks!
----- Update -----
I tried to stub the repository to return a Note object as Dave Marshall mentioned in his answer, however I'm now receiving another error.
1) OneTimeNoteTest::testShouldReturnNoteObj
BadMethodCallException: Method Mockery_0_OneTimeNote_Repositories_EloquentNoteRepository::delete() does not exist on this mock object
I do have a delete() method in my repository and I know it's working when I test my route in the browser.
public function delete($id)
{
Note::find($id)->delete();
}
You are stubbing the note repository to return a string, PHP is then trying to retrieve the id attribute of a string, hence the error.
You should stub the repository to return a Note object, something like:
$this->mock->shouldReceive('find')->once()->andReturn(new Note());
Building upon Dave's answer, I was able to figure out what my problem is. I wasn't mocking the delete() method. I didn't understand the need to mock each individual method in my controller that would be called.
I just added this line:
$mock->shouldReceive('delete')->once()->andReturnNull();
Since my delete method is just deleting the note after it is found, I went ahead and mocked it but set it to return null.

Controller Unit Test fails with SQLSTATE[42000] error

I want to unit test a controller action and have some problem toio excecute it.
The Error i got is the following:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an
error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'questionExists'
at line 1
The Method:
questionExists
is defined inside the Question Model.
My test function looks like this:
public function testView() {
$result = $this->testAction('/questions/questions/view/1', array('return' => 'vars'));
}
The Controller action i want to test looks like this:
public function view($id = null) {
if (!$this->Question->questionExists($id, 'id_virtual')) {
throw new NotFoundException(__('Invalid question'));
}
$options = array('conditions' => array('Question.id_virtual' => $id));
$this->set('question', $this->Question->find('first', $options));
}
So this is very confusing to me.
Can anybody point me to the right direction ?
Your model class is not found, CakePHP creates an instance on the fly for that table but this is not more than the basic Model class. When the code is then called it tries to call that method on an instance that is not your Question model in your app. You'll have to figure out what that happens.

Grails Controller Testing - Problems with dynamic methods

I'm running some old (but valid, i'm told) tests on a legacy application, and notice that many of them arent working. The error message usually is 'No method signature for some dymamic method'
After using mockDomain I managed to solve that problem.
However, I can't figure out how to test controllers that create objects inside.
For example, I created a sample controller (omitted import statements)
package com.tmp
class DummyController2 {
def index = { }
def createObject={
def emp= new Emp(name:'name',description:'description')
if (emp.validate()){
render 'OK'
}
else{
render 'FAIL'
}
}
}
And then the sample controllerTest
package com.tmp
class DummyController2Tests extends ControllerUnitTestCase{
DummyController2 controller
public void setUp(){
super.setUp()
controller = new DummyController2()
}
public DummyController2Tests(){
super(DummyController2Tests)
}
public void tearDown(){
super.tearDown()
}
void testCreateObject(){
assertEquals 'OK',controller.createObject()
}
}
Now when I run this test, I get the
groovy.lang.MissingMethodException: No
signature of method: Emp.validate() is
applicable for argument types: ()
values: []
Is there a workaround on this? Adding mockDomain statements inside the controller seems very intrusive and wrong. Maybe its just that I'm using an old grails (1.2.1)?
Thanks in advance
Your domain class is not mocked. Add to setUp():
mockDomain Emp