I am writing the unit tests to test a Model class.
First I have a testAddStudent() test case that adds some data to db.
Then I have another test case to retrieve the record I just added.
The code I have looks like the following:
class Model_STest extends PHPUnit_Framework_TestCase {
protected $_student;
public function setUp() {
error_log("Entered setup");
parent::setUp();
$this->_student = new Application_Model_Student();
}
public function testInit() {
error_log("Entered testInit");
}
public function testAddStudent() {
error_log("Entered testAddStudent");
$testData = array(
'name' => 'abc',
'teacher' => 'amyac',
'start_date' => '2012_08_06'
);
$result = $this->_student->addStudent($testData);
error_log("result is ".print_r($result, true));
$this->assertGreaterThan(0, $result);
}
/**
* #depends testAddStudent
*/
public function testGetStudent($result) {
error_log("Entered testGetStudent, finding student id: $result");
$resultx = $this->_student->getStudent($result);
$this->assertEquals($result, $resultx);
}
}
However, when I run the phpunit test (using command line), The logs show me that the student id being searched is 0. Whereas the testAddStudent is returning me the student id as a non-zero value.
What am I doing wrong?
I have
PHPUnit 3.6.11 by Sebastian Bergmann.
Any help is greatly appreciated.
Thanks!
You should return $result from your testAddStudent() function.
(The returned value from the depended-on function is passed to depending function.)
You might also consider doing the same with your Application_Model_Student instance, instead of using a protected class variable. Here is your example rewritten to show that. (I used a dummy Application_Model_Student that does just enough to pass the test.)
class Application_Model_Student{
private $d;
function addStudent($d){$this->d=$d;return 1;}
function getStudent($ix){return $ix;}
}
//----------------------
class Model_STest extends PHPUnit_Framework_TestCase {
public function testAddStudent() {
error_log("Entered testAddStudent");
$testData = array(
'name' => 'abc',
'teacher' => 'amyac',
'start_date' => '2012_08_06'
);
$student = new Application_Model_Student();
$result = $student->addStudent($testData);
error_log("result is ".print_r($result, true));
$this->assertGreaterThan(0, $result);
return array($student,$result);
}
/**
* #depends testAddStudent
*/
public function testGetStudent($data) {
list($student,$result)=$data;
error_log("Entered testGetStudent, finding student id: $result");
$resultx = $student->getStudent($result);
$this->assertEquals($result, $resultx);
}
}
P.S. Note the implementation I used for getStudent to get it to pass! I imagine this is not the test you intended to do.
Related
I'm trying to add a unit testing framework to an already existing Laravel project. I've read the PHPUnit manual and I'm trying to set up a sqlite environment using .xml datasets to populate the test data and a main migration to create the schema but the actual test data does not seem to be populating into the tables.
I started out adding phpunit and dbunit to the composer.json file and updating them. I added vendor/bin to $PATH so the VM will know where to find it.
I then expanding the existing TestCase class with getConnection(), getDataSet() and setUp() which contains
class TestCase extends Illuminate\Foundation\Testing\TestCase {
static private $pdo = null;
private $conn = null;
public function setUp() {
parent::setUp();
Artisan::call('migrate');
$this->seed();
}
public function createApplication() {
$unitTesting = true;
$testEnvironment = 'testing';
return require __DIR__ . '/../../bootstrap/start.php';
}
public function getDataSet() {
parent::getDataSet();
}
public function getConnection() {
if ($this->conn === null) {
if (self::$pdo == null) {
self::$pdo = new PDO('sqlite::memory:');
}
$this->conn = $this->createDefaultDBConnection(self::$pdo, ':memory:');
}
return $this->conn;
}
}
The Illuminate\Foundation\Testing\Testcase I changed to :
abstract class TestCase extends \PHPUnit_Extensions_Database_TestCase {
....
}
This done, I created an XML dataset
<?xml version="1.0" ?>
<dataset>
<table name="a_table">
<column>id</column>
<column>data1</column>
<column>data2</column>
<row>
<value>1</value>
.....
.....
</row>
<row>
.....
</row>
</table>
</dataset>
I used the artisan convert migrations command to create the schema.
Then I wrote my first test.
class ImportantClassTest extends TestCase {
/**
* #author Me
*
*
* Tests the functionality of some function
* #dataProvider ImportantFunctionData();
*/
public function testthisImportantFunction($an_id,$an_amount,$another_amount,$starting_rows,$expected_rows)
{
$this->assertEquals($this->getConnection()->getRowCount('a_table'),$starting_rows);
$result = ImportantClass::ImportantFunction($an_id, $an_amount);
$this->assertEquals($another_amount,$result);
$this->assertEquals($this->getConnection()->getRowCount('a_table'),$expected_rows);
}
public function ImportantFunctionData()
{
return array(
array(1337,1000,180,10,10),
array(1338,3900,900,10,11)
);
}
public function getDataSet()
{
return $this->createXMLDataSet(dirname(__FILE__) . '/_files/ImportantFunctionData.xml');
} }
I added config/testing/database.php :
return array(
'default' => 'sqlite',
'connections' => array(
'sqlite' => array(
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
)
),
);
When I run the test, the migration occurs to create the db in sqlite memory, but the data does not appear to populate. With the row checking I get this error :
1) ImportantClass::testthisImportantFunction with data set #0 (1337,
1000, 180, 10, 10) PDOException: SQLSTATE[HY000]: General error: 1 no
such table: a_table
and just the result assertion on it's own
1) ImportantClass::testthisImportantFunction with data set #0 (1337,
1000, 180, 10, 10) Failed asserting that 1000 matches expected 180.
So in neither case does it appear that phpunit is populating the fixtures correctly.
Can anyone see where I'm going wrong?
I followed the docs to create a custom report but keep failing to generate the report in the CMS. Has anyone else had this problem? I noticed that with older versions, the config had to include the report, but I see no sign of this in 3.1.
Here is the contents of CustomSideReport.php
class CustomSideReport_Day extends SideReport {
public function title() {
return "Event Calendar";
}
public function records() {
return Page::get()->sort("Title");
}
public function fieldsToShow() {
return array(
"Title" => array("NestedTitle", array("2"))
);
}
}
I have the done the usual dev/build and flush, but still nothing appears.
The documentation has now been updated to correctly show how to make custom site reports.
In SilverStripe 3.1 the class should extend SS_Report instead of SideReport.
Try this:
class CustomSideReport_Day extends SS_Report {
public function title() {
return 'Event Calendar';
}
public function sourceRecords($params = null) {
return Page::get()->sort('Title');
}
public function columns() {
$fields = array(
'Title' => 'Title'
);
return $fields;
}
}
Also note that records() has changed to sourceRecords($params = null) and fieldsToShow() has changed to columns().
How would I go about binding a Symfony config tree to a class rather than returning an array?
Using Symfony\Component\Config\Definition\Processor returns an array.
In my case I want the config to be bound to a class so I can use methods to combine parts of the data.
Here is a simple example of my use case. I want the config bound to a class so I can use a method to join table.name and table.version together (my actual use case is more complex, but this is a simple example)
config.yml
db:
table:
name: some_table
version: v2
ConfigurationInterface
class DBConfiguration implements ConfigurationInterface
{
/**
* {#inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('db');
$rootNode
->children()
->arrayNode('table')
->children()
->scalarNode('name')->isRequired()->end()
->scalarNode('version')->end()
->end()
->end()
;
return $treeBuilder;
}
}
Class I want to bind the config to
class DB
{
public $table;
public function __construct()
{
$this->table = new Table();
}
}
class Table
{
public $name;
public $version;
/**
* #return string
* Calculate the full table name.
*/
public function getTableName()
{
return $this->name.'-'.$this->version;
}
}
The Symfony Config component doesn't support that.
However, in a Symfony project, this is usually done at the container compile phase. In your bundle's Extension class, you will have access to the configuration tree of your bundle in array form.
You can then take this array and assign it to a service defined in the service container that will create your config object.
This is exactly how DoctrineBundle's configuration class is built:
Abstract services (for the configuration and the factory) are defined in dbal.xml
When loading DoctrineBundle's extension, an instance of the abstract config service is created for each defined connection.
An instance of the abstract factory service is created for each defined connection.
The options array is then passed to the abstract factory service along with the configuration
When creating an instance, the factory then does the necessary transformations.
As far as I know, Symfony has no native support for this, however, you could implement it yourself. You could use subset of Symfony Serializer Component in charge of deserialization, but I think it would be an overkill. Especially since I don't see any PublicPropertyDenormalizer, only GetSetMethodNormalizer (which is denormalizer too). Therefor you would have to either make your config objects have get/set methods or roll PublicPropertyDenormalizer on your own. Possible but it really seems like an overkill and doesn't look like helping much:
Symfony Serializer Component
$array = [
'field1' => 'F1',
'subobject' => [
'subfield1' => 'SF1',
],
];
class MyConfigObject implements Symfony\Component\Serializer\Normalizer\DenormalizableInterface
{
private $field1;
private $subobject;
public function getField1()
{
return $this->field1;
}
public function setField1($field1)
{
$this->field1 = $field1;
}
public function getSubobject()
{
return $this->subobject;
}
public function setSubobject(SubObject $subobject)
{
$this->subobject = $subobject;
}
public function denormalize(\Symfony\Component\Serializer\Normalizer\DenormalizerInterface $denormalizer, $data, $format = null, array $context = array())
{
$obj = new static();
$obj->setField1($data['field1']);
$obj->setSubobject($denormalizer->denormalize($data['subobject'], 'SubObject'));
return $obj;
}
}
class SubObject
{
private $subfield1;
public function getSubfield1()
{
return $this->subfield1;
}
public function setSubfield1($subfield1)
{
$this->subfield1 = $subfield1;
}
}
$normalizer = new \Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer();
$obj = (new MyConfigObject())->denormalize($normalizer, $array);
Native PHP Way
Imo this is a lot easier than above as Symfony Serializer wasn't really ment for that.
$array = [
'field1' => 'F1',
'subobject' => [
'subfield1' => 'SF1',
],
];
trait Denormalizable
{
public function fromArray($array)
{
foreach ($array as $property => $value) {
if (is_array($value)) {
if ($this->$property instanceof ArrayDenormalizableInterface) {
$this->$property->fromArray($value);
} else {
$this->$property = $value;
}
} else {
$this->$property = $value;
}
}
}
}
interface ArrayDenormalizableInterface
{
public function fromArray($array);
}
class MyConfigObject implements ArrayDenormalizableInterface
{
use Denormalizable;
public $field1;
public $subobject;
public function __construct()
{
$this->subobject = new SubObject();
}
}
class SubObject implements ArrayDenormalizableInterface
{
use Denormalizable;
public $subfield1;
}
$myConf = new MyConfigObject();
$myConf->fromArray($array);
Whatever way you choose, you can now just take array returned from symfony processor and turn it into a config object you need.
I get this error message when i create since i have created a simple twig filter. The message is not clear at all.
An exception has been thrown during the compilation of a template
("Warning: Illegal offset type in app/cache/dev/classes.php line
3342")
My filter:
class simpleFilter extends Twig_Extension
{
public function getFilters()
{
return array('simpleFilter' => new Twig_SimpleFilter($this, 'simpleFilter'));
}
public function simpleFilter($value)
{
return 'test'.$value;
}
public function getName()
{
return 'some_extension';
}
}
My config
my.twig.extension.simpleFilter:
class: Bundle\Twig\Filter\SimpleFilter
tags:
- { name: twig.extension }
Am i missing something?
Try to change your getFilters to look like this:
public function getFilters()
{
return array(
new Twig_SimpleFilter('simpleFilter', array($this, 'simpleFilter'))
);
}
I had to use Twig_Filter_Method
public function getFilters()
{
return array(
new Twig_Filter_Method('simpleFilter', array($this, 'simpleFilter'))
);
}
even if i do not know the difference beetween them.
I need to mock Laravel's Eloquent\Model with Mockery and it is kind of tricky because it uses static methods.
I solved this issue with the following code but I wonder if there is a better/smarter way to do this.
<?php
use Ekrembk\Repositories\EloquentPostRepository;
class EloquentPostRepositoryTest extends TestCase {
public function __construct()
{
$this->mockEloquent = Mockery::mock('alias:Ekrembk\Post');
}
public function tearDown()
{
Mockery::close();
}
public function testTumuMethoduEloquenttenAldigiCollectioniDonduruyor()
{
$eloquentReturn = 'fake return';
$this->mockEloquent->shouldReceive('all')
->once()
->andReturn($eloquentDongu);
$repo = new EloquentPostRepository($this->mockEloquent);
$allPosts = $repo->all();
$this->assertEquals($eloquentReturn, $allPosts);
}
}
Tough to tell without the source of "Ekrembk\Repositories\EloquentPostRepository", but, I see a couple of issues. It looks like within your EloquentPostRepository, you're calling a static. You shouldn't do that. It makes it hard to test (as you've discovered). Assuming that Ekrembk\Post extends from Eloquent, you can do this instead:
<?php
namespace Ekrembk\Repositories
class EloquentPostRepository {
protected $model;
public __construct(\Ekrembk\Post $model) {
$this->model = $model;
}
public function all()
{
$query = $this->model->newQuery();
$results = $query->get();
return $results;
}
}
Then, your test will be simpler:
<?php
use Ekrembk\Repositories\EloquentPostRepository;
class EloquentPostRepositoryTest extends TestCase {
public function tearDown()
{
Mockery::close();
}
public function testTumuMethoduEloquenttenAldigiCollectioniDonduruyor()
{
$mockModel = Mockery::mock('\Ekrembk\Post');
$repo = new EloquentPostRepository($mockModel);
$eloquentReturn = 'fake return';
$mockModel->shouldReceive('newQuery')->once()->andReturn($mockQuery = m::mock(' \Illuminate\Database\Eloquent\Builder'));
$result = $mockQuery->shouldReceive('get')->once()->andReeturn($eloquentReturn);
$this->assertEquals($eloquentReturn, $result);
}
}
Didn't test the above so it might have issues, but you should get the idea.
If you look in Illuminate\Database\Eloquent\Model, you'll see that "public static function all" is really just calling "get" on an instantiated eloquent model.