phpunit dataprovider out of scope - phpunit

The class I'm testing:
class Calculate {
public $x;
public $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
public function add(): int {
return $this->x + $this->y;
}
}
My test code:
use PHPUnit\Framework\TestCase;
class CalculateTest extends TestCase {
public function additionProvider() {
return [
[1, 2],
[5, 8],
[-1, 10],
[66, 3],
[9, 4]
];
}
/**
* #dataProvider additionProvider
*/
public function testGetIsOk($x, $y): Calculate {
$c = new Calculate($x, $y);
var_dump($c);
$this->assertEquals($x, $c->x);
$this->assertEquals($y, $c->y);
return $c;
}
/**
* #depends testGetIsOk
*/
public function testAddIsNormal(Calculate $c):void {
$this->assertEquals($c->x + $c->y, $c->add());
}
}
There are 5 elements in the dataprovider, but the test result shows that the 6th test is error.
PHPUnit 6.3.0 by Sebastian Bergmann and contributors.
.....E 6 / 6 (100%)
Time: 97 ms, Memory: 8.00MB
There was 1 error:
1) CalculateTest::testAddIsNormal
TypeError: Argument 1 passed to CalculateTest::testAddIsNormal() must be an inst
ance of Calculate, null given
Thanks.

Ok, I check the issue on github, and I finally know that I cannot pass the result of a test that get data from data providers to another test.
There is it: https://github.com/sebastianbergmann/phpunit/issues/611

Related

Symfony EasyAdmin3: Argument 1 passed must be an instance of App\Entity

I use easyadmin for Symfony (I am a beginner), I'm stuck on this problem:
Argument 1 passed to App\Entity\MyOrder::setCarrier() must be an instance of App\Entity\Carrier or null, int given, called in /Users/My/Sites/test/src/Controller/Admin/MyOrderCrudController.php
(line in code: $myorder->setCarrier(2);)
I have this problem for all field with an relation.
however, My Entity:
/**
* #ORM\ManyToOne(targetEntity=Delivery::class, inversedBy="myOrder")
*/
private $delivery;
...
public function getCarrier(): ?carrier
{
return $this->carrier;
}
public function setCarrier(?carrier $carrier): self
{
$this->carrier = $carrier;
return $this;
}
...
My CrudController:
namespace App\Controller\Admin;
use App\Entity\MyOrder;
use App\Entity\Carrier;
use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\ArrayField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Router\CrudUrlGenerator;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
class MyOrderCrudController extends AbstractCrudController
{
private $entityManager;
private $adminUrlGenerator;
public function __construct(EntityManagerInterface $entityManager, AdminUrlGenerator $adminUrlGenerator)
{
$this->entityManager = $entityManager;
$this->adminUrlGenerator = $adminUrlGenerator;
}
public static function getEntityFqcn(): string
{
return MyOrder::class;
}
public function configureCrud(Crud $crud): Crud
{
return $crud->setDefaultSort(['id' => 'DESC']);
}
public function configureActions(Actions $actions): Actions
{
$updateDelivery = Action::new('updateDelivery', 'Delivery up', 'fas fa-truck')->linkToCrudAction('updateDelivery');
return $actions
->add('detail', $updateDelivery)
->add('index', 'detail');
}
public function updateDelivery(AdminContext $context)
{
$myorder = $context->getEntity()->getInstance();
$myorder->setCarrier(2);
$this->entityManager->flush();
$url = $this->adminUrlGenerator->setRoute('admin', [])->generateUrl();
return $this->redirect($url);
}
setCarrier only accept a Carrier object. You can't pass "2" (I suppose it's the carrier id).
Try this :
$carrier = $this->entityManager->find(Carrier::class, 2);
$myorder->setCarrier($carrier);
PS : There's a typo in your entity (a class name has the first letter in uppercase, so "Carrier" instead of "carrier")

How to close DB connections and reduce their number in functional PHPUnit tests for a ZF3 application?

Some years ago I already created a very similar or even nearly the same question on StackOverflow. I got great detailed answers, but they didn't lead to a solution of my problem. Now, the problem became even bigger and I'm starting the second attempt to solve this here. Since the code has been changed, I don't want to update the original question. It would be a too big update and the answers might perhaps not match to the new version of the question. So I'm formulating it as a new one:
I'm writing functional tests for a Zend Framework 3 application by using
zendframework/zend-test 3.2.2,
phpunit/phpunit 6.5.14, and
phpunit/dbunit 3.0.3
The most of the tests are a kind of controller tests. The test code calls a URI / an action by using the Zend\Test\PHPUnit\Controller\AbstractControllerTestCase#dispatch(...) and analyzes 1. the response / output data and 2. the changes at the database (if it was a writing call like "create foo"), e.g.:
/**
...
* #dataProvider provideDataForShowOrderAccess
*/
public function testShowOrderAccess(string $username, int $responseStatusCode)
{
...
$this->createOrder(...);
$this->reset();
$_SERVER['AUTH_USER'] = $username;
...
$this->dispatch($showUrl);
$this->assertResponseStatusCode($responseStatusCode);
}
/**
...
* #dataProvider provideDataForShowOrder
*/
public function testShowOrder(string $username, bool $isOwner)
{
...
$this->createOrder($connectionType, $endpointSourceType);
$this->reset();
$_SERVER['AUTH_USER'] = $username;
// testing the access by the owner
$orderId = 1;
$showUrl = '/order/show/' . $orderId;
$this->dispatch($showUrl);
if ($isOwner) {
$this->assertResponseStatusCode(Response::STATUS_CODE_200);
$this->assertModuleName('Order');
$this->assertControllerName('Order\Controller\Process');
$this->assertControllerClass('ProcessController');
$this->assertMatchedRouteName('order/show');
/** #var Foo $foo */
$foo = $this->getApplication()->getMvcEvent()->getResult()->getVariable('foo', null);
$fooData = $createParams['foo'];
$barData = $barData['bar'];
$this->assertNotNull($bar);
$this->assertInstanceOf(Foo::class, $foo);
$this->assertEquals($orderId, $foo->getId());
$this->assertEquals($fooData['bar'], $foo->getBar());
...
} else {
$this->assertResponseStatusCode(Response::STATUS_CODE_302);
}
}
For every single test the database gets reset.
The problem is, that the number of database connections is growing and growing and growing -- with every next test. Currently there are about 350 (SHOW GLOBAL STATUS LIKE 'max_used_connections';) connections for 102 tests. (As a workaround I have to increase the MySQL's max_connections more and more.)
I tried to decrease the number of connections by putting logic like $this->dbAdapter->getDriver()->getConnection()->disconnect(); or/and $this->entityManager->getConnection()->close(); to the tearDown() of my super-class for controller tests. This way I got the number of the connections reduced by about 90. But the most of the connections still don't get killed.
How to close DB connections and significantly reduce the number of concurrently open connections in functional / controller PHPUnit tests for a ZF3 application?
Additional information: the most relevant parts of my code
AbstractControllerTest
namespace Base\Test;
use Doctrine\ORM\EntityManager;
use PDO;
use PHPUnit\DbUnit\Database\DefaultConnection;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
/**
* Class AbstractControllerTest
*
* #package Base\Test
*/
abstract class AbstractControllerTest extends AbstractHttpControllerTestCase
{
use DatabaseConnectionTrait;
/**
* #var string
*/
static private $applicationConfigPath;
/** #var Adapter */
protected $dbAdapter;
/** #var EntityManager */
protected $entityManager;
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
$this->setApplicationConfig(include self::$applicationConfigPath);
}
public static function setApplicationConfigPath(string $applicationConfigPath)
{
self::$applicationConfigPath = $applicationConfigPath;
}
protected function tearDown()
{
// Connections: 354
// Time: 5.7 minutes, Memory: 622.00MB
// OK (102 tests, 367 assertions)
// no optimization
// Connections: 326 (26 connections less)
// Time: 5.86 minutes, Memory: 620.00MB
// OK (102 tests, 367 assertions)
// if ($this->dbAdapter && $this->dbAdapter instanceof Adapter) {
// $this->dbAdapter->getDriver()->getConnection()->disconnect();
// }
// Connections: 354
// Time: 5.67 minutes, Memory: 620.00MB
// OK (102 tests, 367 assertions)
// $this->entityManager->close();
// Connections: 291 (63 connections less)
// Time: 5.63 minutes, Memory: 622.00MB
// OK (102 tests, 367 assertions)
// $this->entityManager->getConnection()->close();
// Connections: 264 (90 connections less)
// Time: 5.7 minutes, Memory: 620.00MB
// OK (102 tests, 367 assertions)
// if ($this->dbAdapter && $this->dbAdapter instanceof Adapter) {
// $this->dbAdapter->getDriver()->getConnection()->disconnect();
// }
// $this->entityManager->getConnection()->close();
// Connections: 251
// Time: 4.71 minutes, Memory: 574.00MB
// OK (102 tests, 367 assertions)
// After removing initialization of the EntityManager and the DbAdapter in the constructor and the setUp().
// closing DB connections
if ($this->dbAdapter && $this->dbAdapter instanceof Adapter) {
$this->dbAdapter->getDriver()->getConnection()->disconnect();
}
if ($this->entityManager && $this->entityManager instanceof EntityManager) {
$this->entityManager->getConnection()->close();
}
$reflectionObject = new \ReflectionObject($this);
foreach ($reflectionObject->getProperties() as $prop) {
if (!$prop->isStatic() && 0 !== strpos($prop->getDeclaringClass()->getName(), 'PHPUnit_')) {
$prop->setAccessible(true);
$prop->setValue($this, null);
}
}
$this->reset();
$this->application = null;
gc_collect_cycles();
unset($_SERVER['AUTH_USER']);
parent::tearDown();
}
protected function retrieveActualData($table, $idColumn, $idValue)
{
$sql = new Sql($this->getDbAdapter());
$select = $sql->select($table);
$select->where([$table . '.' . $idColumn . ' = ?' => $idValue]);
$statement = $sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$data = $result->current();
// Decreases the total number of the connections by 1 less.
// $this->dbAdapter->getDriver()->getConnection()->disconnect();
return $data;
}
protected function getEntityManager()
{
$this->entityManager = $this->entityManager
?: $this->getApplicationServiceLocator()->get('doctrine.entitymanager.orm_default')
;
return $this->entityManager;
}
protected function getDbAdapter()
{
$this->dbAdapter = $this->dbAdapter
?: $this->getApplicationServiceLocator()->get('Zend\Db\Adapter\Adapter')
;
return $this->dbAdapter;
}
}
DatabaseConnectionTrait
namespace Base\Test;
use PDO;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\Database\DefaultConnection;
use PHPUnit\DbUnit\InvalidArgumentException;
trait DatabaseConnectionTrait
{
/**
* #var array
*/
static private $dbConfigs;
/**
* #var PDO
*/
static private $pdo;
/**
* #var Connection
*/
private $connection;
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
}
/**
* #return Connection
*/
public function getConnection()
{
if (! $this->connection) {
if (! self::$dbConfigs) {
throw new InvalidArgumentException(
'Set the database configuration first.'
. ' '. 'Use the ' . self::class . '::setDbConfigs(...).'
);
}
if (! self::$pdo) {
self::$pdo = new PDO(
self::$dbConfigs['dsn'],
self::$dbConfigs['username'],
self::$dbConfigs['password'],
[PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'']
);
}
$this->connection = $this->createDefaultDBConnection(self::$pdo, self::$dbConfigs['database']);
}
return $this->connection;
}
public static function setDbConfigs(array $dbConfigs)
{
self::$dbConfigs = $dbConfigs;
}
/**
* Creates a new DefaultDatabaseConnection using the given PDO connection
* and database schema name.
*
* #see The original PHPUnit\DbUnit\TestCaseTrait#createDefaultDBConnection(...).
*
* #param PDO $connection
* #param string $schema
*
* #return DefaultConnection
*/
protected function createDefaultDBConnection(PDO $connection, $schema = '')
{
return new DefaultConnection($connection, $schema);
}
}
DatabaseInitializer
namespace Base\Test;
/**
* Class DatabaseInitializer
*
* #package Base\Test
*/
class DatabaseInitializer
{
use DatabaseConnectionTrait;
/**
* #var string
*/
private $database;
public function __construct(array $dbConfigs)
{
$this->database = $dbConfigs['database'];
self::$dbConfigs = $dbConfigs;
}
public function setUp()
{
$schemaSql = file_get_contents(self::$dbConfigs['scripts']['schema']);
$storedProceduresSql = file_get_contents(self::$dbConfigs['scripts']['stored-procedures']);
$basicDataSql = file_get_contents(self::$dbConfigs['scripts']['basic-data']);
$testDataSqlSet = array_map(function ($sqlFile) {
return file_get_contents($sqlFile);
}, self::$dbConfigs['scripts']['test-data']);
$this->dropDatabase();
$this->createDatabase();
$this->useDatabase();
$this->createSchema($schemaSql);
$this->createStoredProcedures($storedProceduresSql);
$this->createBasicData($basicDataSql);
$this->createTestData($testDataSqlSet);
}
public function tearDown()
{
self::$pdo = null;
}
protected function createDatabase()
{
$this->getDatabaseConnection()->exec('CREATE DATABASE IF NOT EXISTS ' . $this->database . ';');
}
protected function useDatabase()
{
$this->getDatabaseConnection()->exec('USE ' . $this->database . ';');
}
protected function createSchema(string $sql)
{
$this->getDatabaseConnection()->exec($sql);
}
protected function createBasicData(string $sql)
{
$this->getDatabaseConnection()->exec($sql);
}
protected function createTestData(array $sqlSet = [])
{
foreach ($sqlSet as $sql) {
$this->getDatabaseConnection()->exec($sql);
}
}
protected function createStoredProcedures(string $sql)
{
$statement = $this->getDatabaseConnection()->prepare($sql);
$statement->execute();
}
protected function dropDatabase()
{
$this->getDatabaseConnection()->exec('DROP DATABASE IF EXISTS ' . $this->database . ';');
}
protected function getDatabaseConnection()
{
return $this->getConnection()->getConnection();
}
}
Bootstrap
namespace Test;
use Base\Test\AbstractControllerTest;
use Base\Test\AbstractDbTest;
use Base\Test\DatabaseInitializer;
use Doctrine\ORM\EntityManager;
use RuntimeException;
use Zend\Loader\AutoloaderFactory;
use Zend\Mvc\Service\ServiceManagerConfig;
use Zend\ServiceManager\ServiceManager;
error_reporting(E_ALL | E_STRICT);
ini_set('memory_limit', '2048M');
chdir(__DIR__);
/**
* Sets up the MVC (application, service manager, autoloading) and the database.
*/
class Bootstrap
{
/** #var ServiceManager */
protected $serviceManager;
protected $applicationConfigPath;
/** #var EntityManager */
protected $entityManager;
public function __construct()
{
$this->applicationConfigPath = __DIR__ . '/../config/application.config.php';
}
/**
* Sets up the
*/
public function init()
{
// autoloading setup
static::initAutoloader();
// application configuration & setup
$applicationConfig = require_once $this->applicationConfigPath;
$this->prepareApplication($applicationConfig);
// database configuration & setup
$dbConfigs = $this->serviceManager->get('Config')['db'];
$this->setUpDatabase($dbConfigs);
// listeners & application bootstrap
$listeners = $this->prepareListeners();
$this->bootstrapApplication($listeners);
}
public function chroot()
{
$rootPath = dirname(static::findParentPath('module'));
chdir($rootPath);
}
protected function prepareApplication($config)
{
$serviceManagerConfig = isset($config['service_manager']) ? $config['service_manager'] : [];
$serviceManagerConfigObject = new ServiceManagerConfig($serviceManagerConfig);
$this->serviceManager = new ServiceManager();
$serviceManagerConfigObject->configureServiceManager($this->serviceManager);
$this->serviceManager->setService('ApplicationConfig', $config);
$this->serviceManager->get('ModuleManager')->loadModules();
}
protected function prepareListeners()
{
$listenersFromAppConfig = [];
$config = $this->serviceManager->get('config');
$listenersFromConfigService = isset($config['listeners']) ? $config['listeners'] : [];
$listeners = array_unique(array_merge($listenersFromConfigService, $listenersFromAppConfig));
return $listeners;
}
protected function bootstrapApplication($listeners)
{
$application = $this->serviceManager->get('Application');
$application->bootstrap($listeners);
}
protected function setUpDatabase(array $dbConfigs)
{
$databaseInitializer = new DatabaseInitializer($dbConfigs);
$databaseInitializer->setUp();
AbstractDbTest::setDbConfigs($dbConfigs);
AbstractControllerTest::setApplicationConfigPath($this->applicationConfigPath);
AbstractControllerTest::setDbConfigs($dbConfigs);
}
protected function initAutoloader()
{
$vendorPath = static::findParentPath('vendor');
if (file_exists($vendorPath.'/autoload.php')) {
include $vendorPath.'/autoload.php';
}
if (! class_exists('Zend\Loader\AutoloaderFactory')) {
throw new RuntimeException(
'Unable to load ZF2. Run `php composer.phar install`'
);
}
AutoloaderFactory::factory(array(
'Zend\Loader\StandardAutoloader' => array(
'autoregister_zf' => true,
'namespaces' => array(
__NAMESPACE__ => __DIR__,
),
),
));
}
protected function findParentPath($path)
{
$dir = __DIR__;
$previousDir = '.';
while (!is_dir($dir . '/' . $path)) {
$dir = dirname($dir);
if ($previousDir === $dir) {
return false;
}
$previousDir = $dir;
}
return $dir . '/' . $path;
}
}
$bootstrap = new Bootstrap();
$bootstrap->init();
$bootstrap->chroot();
Since we don't see your controller, your repositories etc. we can't say you "there' mistake". Normally, you should make your connection for database test on setUp method, and destroy it on tearDown method. And you shouldn't start connection for application. Application should start that connection when it needs. Since you're using Doctrine, it does that. Why you're creating/calling EntityManager before tests?
What happens if you run only one test instead whole testcase? How many connections happens? Maybe you're making a mistake in a controller? In a repository maybe?
Here what i see when i look that code;
I couldn't see where initializer is using. Where do you using it? I didn't like that methods in it.
Your both DatabaseConnectionTrait and AbstractControllerTest classes have _construct method. If a class overwrites a method which is defined in trait, class' method works. Why trait has that method?
Are you sure you're not doing same thing over and over again?getDatabaseConnection, getConnection, $this->getConnection()->getConnection();
Where you define static $em property?
unset that reflection object when you done with it. I know it's easy and faster way to desctruct all properties, but you should consider to do it yourself. It'll be better way to manage your ram.
Why you trying to destruct all properties of class in tearDown method with reflection? Destroy connection and let php manage garbage.
Why you destroy database on tearDown method? If you provide your test-data to phpunit correctly, you don't need that. Check tearDownOperation of DbUnit.
I suggest you run that tests one by one instead whole test-case and check connection counts. Also you should test your Repositories with DbUnit to be sure they're working right. Since Repositories responsible on database, maybe that connection count increasing on them.

PhpUnit dataProviders vs Coverage

I decided, that it will be fine if I use data providers but when i try to generate code coverage whole tested class has 0% coverage.. Can someone tell me why?
Test class:
class AuthorDbManagerTest extends AbstractDbManagerTest
{
public function setUp()
{
parent::setUp();
}
/**
* #dataProvider instanceOfProvider
* #param bool $isInstanceOf
*/
public function testInstances(bool $isInstanceOf)
{
$this->assertTrue($isInstanceOf);
}
public function instanceOfProvider()
{
$manager = new AuthorDbManager($this->getEntityManagerMock());
return [
"create()" => [$manager->create() instanceof Author],
"save()" => [$manager->save(new Author()) instanceof AuthorDbManager],
"getRepository" => [$manager->getRepository() instanceof EntityRepository],
];
}
}
Tested class:
class AuthorDbManager implements ManagerInterface
{
protected $entityManager;
protected $repository;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
$this->repository = $entityManager->getRepository(Author::class);
}
public function create(array $data = [])
{
return new Author();
}
public function getRepository(): EntityRepository
{
return $this->repository;
}
public function save($object): ManagerInterface
{
$this->entityManager->persist($object);
$this->entityManager->flush();
return $this;
}
}
Why my code coverage is 0% on AuthorDbManager?
Screen
The data in the DataProvider is collected before the actual tests start - and there is nothing useful being tested within the testInstances() method.
If you passed the classname and expected class into testInstances($methodName, $expectedClass):
public function testInstances(callable $method, $expectedClass)
{
$this->assertInstanceOf($expectedClass, $method());
}
The dataprovider could return a callable, and the expected result:
"create()" => [[$manager,'create'], Author::class],
then you'd at least be running the code with in the actual test. You may also be better to just pass back a string methodname - 'create', and run that with a locally created $manager instance - $manager->$method() in the test.
In general, it's best to test something as specific as you can - not just letting it convert to a true/false condition.

Converting datetime data on retrieval with user's timezone using date mutators in Laravel 5

I'm saving all datetime data (created_at, updated_at and a custom datetime column: appointment_at) in UTC format.
I would like to retrieve all these dates, and convert them to the user's timezone for display.
I've added these functions to my model thinking this would retrieve the datetime in the user's timezone:
public function getCreatedAtAttribute($value)
{
return $created_at->timezone(Auth::user()->timezone);
}
public function getUpdatedAtAttribute($value)
{
return $updated_at->timezone(Auth::user()->timezone);
}
public function getAppointmentAtAttribute($value)
{
return $appointment_at->timezone(Auth::user()->timezone);
}
But I get the following error:
Call to a member function timezone() on a non-object
I'm guessing there's an error in my syntax. Am I missing something? Thanks
UPDATE #1 Made corrections to Note Model and added complete Model below (including corrections by #bernie)
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Note extends Model {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'notes';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['client_id', 'business_id', 'note'];
/**
* Note belonging to client.
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function client()
{
return $this->belongsTo('App\Client');
}
public function getCreatedAtAttribute($value)
{
return $this->created_at->timezone(Auth::user()->timezone);
}
public function getUpdatedAtAttribute($value)
{
return $this->updated_at->timezone(Auth::user()->timezone);
}
public function getAppointmentAtAttribute($value)
{
return $this->appointment_at->timezone(Auth::user()->timezone);
}
Database Model definition
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateNotesTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('notes', function(Blueprint $table)
{
$table->increments('id');
$table->integer('client_id')->unsigned();
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$table->integer('business_id')->unsigned();
$table->foreign('business_id')->references('id')->on('businesses')->onDelete('cascade');
$table->text('note');
$table->dateTime('appointment_at');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('notes');
}
}
More info about the error (after updates by bernie)
ErrorException in Note.php line 40: Undefined property: App\Note::$created_at
in Note.php line 40
at HandleExceptions->handleError('8', 'Undefined property: App\Note::$created_at', '/var/www/html/laravel5/app/Note.php', '40', array()) in Note.php line 40
at Note->getCreatedAtAttribute('2015-09-22 12:50:20') in Model.php line 2669
at Model->mutateAttribute('created_at', '2015-09-22 12:50:20') in Model.php line 2592
at Model->getAttributeValue('created_at') in Model.php line 2557
at Model->getAttribute('created_at') in Model.php line 3263
at Model->__get('created_at') in NotesController.php line 54
at NotesController->show('1')
Solution
public function getCreatedAtAttribute($value)
{
$date = $this->asDateTime($value);
return $date->timezone(\Auth::user()->timezone);
}
or
public function getCreatedAtAttribute($value)
{
$format = $this->getDateFormat();
return Carbon::createFromFormat($format, $value, 'UTC')->setTimezone( \Auth::user()->timezone);
}
Both of these solutions worked for me.
Ah now I see! I realized you're using Accessors and Mutators. You're also overriding the built-in date mutators used for created_at and other dates fields.
So, try this instead :
public function getCreatedAtAttribute($value)
{
// asDateTime() is the built-in date mutator.
$date = $this->asDateTime($value);
return $date->timezone(Auth::user()->timezone);
}
public function getUpdatedAtAttribute($value)
{
$date = $this->asDateTime($value);
return $date->timezone(Auth::user()->timezone);
}
public function getAppointmentAtAttribute($value)
{
$date = $this->asDateTime($value);
return $date->timezone(Auth::user()->timezone);
}

How testing instance of Exception with phpunit

I have this class to testing.
class IpSecurity
{
/** #var array */
private $ipsAllow;
public function __construct(array $ipsAllow)
{
$this->ipsAllow = $ipsAllow;
}
/**
* #param string $clientIp
*
* #return NotFoundHttpException
*/
public function checkIp($clientIp)
{
if (!in_array($clientIp, $this->ipsAllow)) {
throw new NotFoundHttpException('NOT FOUND');
}
}
}
I write a test for testing excettion.
class IpSecurityTest extends \PHPUnit_Framework_TestCase
{
/** #var IpSecurity */
private $ipSecurity;
private $ipsAllow = array(
'192.168.200.21'
);
public function setUp()
{
$this->ipSecurity = new IpSecurity($this->ipsAllow);
}
/**
* #test
* #expectedException(Symfony\Component\HttpKernel\Exception\NotFoundHttpException)
*/
public function invalidClientIp()
{
$this->ipSecurity->checkIp('127.0.0.1');
}
}
This is the test output:
PHPUnit 3.7.37 by Sebastian Bergmann.
Configuration read from /home/pablo/dev/www/app/phpunit.xml
E
Time: 36 ms, Memory: 4.50Mb
There was 1 error:
1) ws\AmneiBundle\Tests\Services\IpSecurityTest::invalidClientIp
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: NOT FOUND
I want test the exception class, not if result is a exception.
You can test it with this code
try
{
$this->ipSecurity->checkIp('127.0.0.1');
}catch( Exception $e )
{
if (!($e instanceof NotFoundHttpException)) {
$this->fail("Unexpected Exception type throwed");
}
}

Resources