I have created the a test for a controller using Cake bake command.
Now, I want to test the function "index" of the controller and for it I do this:
public function testIndex() {
echo "printed";
$result = $this->testAction("/comments/1");
echo "not printed";
}
1 is the param, the id of the post where the comment is. Anyway, the controller works perfectly well, there's no problem with it.
As you can see, the test crashes after calling the testAction method. (it doesn't print the second echo)
I have seen that if the action called on the controller has any call to its model, testAction call won't work. But, if the action to test doesn't have any call to any Model, then, it works perfectly.
Whats happening here?
By the way, both databases, default and test has data in it so it's not either a problem with the database.
Thanks.
UPDATE:
here you have the rest of the testController generated by Cake bake command:
<?php
/* Comments Test cases generated on: 2012-04-12 11:49:17 : 1334224157*/
App::uses('CommentsController', 'Controller');
/**
* TestCommentsController *
*/
class TestCommentsController extends CommentsController {
/**
* Auto render
*
* #var boolean
*/
public $autoRender = false;
/**
* Redirect action
*
* #param mixed $url
* #param mixed $status
* #param boolean $exit
* #return void
*/
public function redirect($url, $status = null, $exit = true) {
$this->redirectUrl = $url;
}
}
/**
* CommentsController Test Case
*
*/
class CommentsControllerTestCase extends CakeTestCase {
/**
* Fixtures
*
* #var array
*/
public $fixtures = array('app.comment');
/**
* setUp method
*
* #return void
*/
public function setUp() {
parent::setUp();
$this->Comments = new TestCommentsController();
$this->Comments->constructClasses();
}
/**
* tearDown method
*
* #return void
*/
public function tearDown() {
unset($this->Comments);
parent::tearDown();
}
When you're testing controllers, make sure to extend the test case class by ControllerTestCase to take advantage of the testAction() method.
Related
when i use raw option to post a data into the database at that time it will work ,it's not showing any error to me at that time when i tried to post a data like a form-data at that time i am getting Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot be null error , How to solve this error [How i am passing headers]1 && [How i pass form-data]2
migration table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBooksTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->length(50)->unique();
$table->binary('image');
$table->integer('price')->unsigned();
$table->text('title');
$table->integer('quantity')->length(2)->unsigned();
$table->integer('ratings')->length(2)->unsigned();
$table->string('author');
$table->longText('description');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('books');
}
}
BooksController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Books;
use App\Models\User;
use App\Http\Requests;
use Symfony\Component\HttpFoundation\Response;
use App\Http\Resources\Books as BooksResource;
use App\Http\Middleware\Authenticate;
class BooksController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function DisplayBooks()
{
$books=Books::all();
return User::find($books->user_id=auth()->id())->books;
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function AddBooks(Request $request)
{
$book=new Books();
$book->name=$request->input('name');
$book->image=$request->input('image');
$book->price=$request->input('price');
$book->title=$request->input('title');
$book->quantity=$request->input('quantity');
$book->ratings=$request->input('ratings');
$book->author=$request->input('author');
$book->description=$request->input('description');
$book->user_id = auth()->id();
$book->save();
return new BooksResource($book);
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function ShowBook($id)
{
$book=Books::findOrFail($id);
if($book->user_id==auth()->id())
return new BooksResource($book);
else{
return response()->json([
'error' => 'UnAuthorized/invalid id'], 401);
}
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function UpdateBook(Request $request, $id)
{
$book=Books::findOrFail($id);
if($book->user_id==auth()->id()){
$book->name=$request->input('name');
$book->image=$request->input('image');
$book->price=$request->input('price');
$book->title=$request->input('title');
$book->quantity=$request->input('quantity');
$book->ratings=$request->input('ratings');
$book->author=$request->input('author');
$book->description=$request->input('description');
$book->save();
return new BooksResource($book);
}
else
{
return response()->json([
'error' => ' Book is not available ith id'], 404);
}
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function DeleteBook($id)
{
$book=Books::findOrFail($id);
if($book->user_id==auth()->id()){
if($book->delete()){
return response()->json(['message'=>'Deleted'],201);
}
}
else{
return response()->json([
'error' => ' Method Not Allowed/invalid Book id'], 405);
}
}
}
I am testing my repository in Laravel and I came across a few issues, most probably with regards to the structure of my methods.
So, my repository looks like:
<?php
namespace Repositories\User;
use App\Test\Models\Entities\User;
use Illuminate\Database\Eloquent\Model;
class UserRepository implements UserInterface
{
/**
* #var Model $userModel
*/
protected $userModel;
/**
* Setting our class $userModel to the injected model
*
* #param Model $userModel
* #return UserRepository
*/
public function __construct(Model $userModel)
{
$this->userModel = $userModel;
}
/**
* Returns the User object associated with the userEmail
*
* #param string $userEmail
* #return User | null
*/
public function getUserByEmail($userEmail)
{
// Search by email
$user = $this->userModel
->where('email', '=', strtolower($userEmail))
->first();
if ($user) {
return $user->first();
}
return null;
}
}
/**
* #param $id
* #param $email
* #param $source
*
* #dataProvider usersDataProvider
*/
public function testGetUserByEmail($id, $email, $source)
{
$user = new User();
$user->id = $id;
$user->email = $email;
$user->user_source_id = $source;
$this->user->shouldReceive('getUserByEmail')->once()
->andReturn($user);
}
I am quite new working with Mockery and am just wondering whether I am following the correct approach in order to test my getUserByEmail($email) method. Please bare in mind that (as expected) getUserByEmail($email) makes a call to the Database.
Also, this is the message that I receive:
PHP Fatal error: Call to a member function connection() on null in /private/var/www/ff-php-prelaunch/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php, which probably implies that there is no initialized connection to the DB.
UPDATE
Btw, my setUp() is as follows:
public function setUp()
{
$this->user = Mockery::mock('App\Test\Models\Entities\User');
parent::setUp();
}
You probably don't extend the default TestCase class provided by Laravel in the tests directory. Your environment is not correct and you have no connection to the database.
If you don't want to actually query the database you should use Mockery to create a mock of your dependencies (here $userModel). You basically create a Mock the following way, I didn't test this code but the general idea is here.
protected function setUp() {
parent::setUp();
$userModelMockedMethods = [
'where' => 'some return'
];
// This is our dependency mock
$userModelMock = Mockery::mock(Model::class, $userModelMockedMethods);
// this mock now will return 'some return' if you call the `where` method
// on it. If you wish the where method to return something callable, you
// should return another mock instead of a string
// This replaces the mock in the dependency manager.
$this->app->instance(Model::class, $UserModelMock);
}
I have two simple entities connected to each other with a OneToMany association.
/**
* #ORM\Entity(repositoryClass="Shopware\CustomModels\JoeKaffeeAbo\Client")
* #ORM\Table(name="joe_kaffee_abo_client")
*/
class Client extends ModelEntity
{
public function __construct() {
$this->abos = new ArrayCollection();
}
/**
* #ORM\OneToMany(targetEntity="Shopware\CustomModels\JoeKaffeeAbo\Abo", mappedBy="client", cascade= "all")
* #var \Doctrine\Common\Collections\ArrayCollection
*/
protected $abos;
public function addAbo($abo)
{
//$this->abos[] = $abo;
$this->abos->add($abo);
}
The second one is Abo:
/**
* #ORM\Entity(repositoryClass="Shopware\CustomModels\JoeKaffeeAbo\Abo")
* #ORM\Table(name="joe_kaffee_abo_abos")
*/
class Abo extends ModelEntity
{
/**
* #ORM\ManyToOne(targetEntity="Shopware\CustomModels\JoeKaffeeAbo\Client",inversedBy="abos")
* #ORM\JoinColumn(name="clientId", referencedColumnName="id")
*/
protected $client;
}
Somehow the join column gets not filled - it seems that doctrine ignores the association I set up. And if I call $client->addAbo($abo) there gets not relation created...and I cant receive the added abos via a getter function which returns the abo array collection.
i want to fetch the data of a menu including its categories in a custom repository by a dql-statement, but it doesn't return the associated entities. I need it as json data, so i added the hydration mode Query::HYDRATE_ARRAY to the function call.
/**
* #ORM\Entity(repositoryClass="Company\Repository\Doctrine\MenuRepository")
* #ORM\Table(name="menu")
*/
class Menu {
/**
* #var \Company\Entity\MenuCategory[]
*
* #ORM\OneToMany(targetEntity="Company\Entity\MenuCategory", mappedBy="menu")
*/
protected $categories;
}
/**
* #ORM\Entity(repositoryClass="Company\Repository\Doctrine\MenuCategoryRepository")
* #ORM\Table(name="menu_category")
*/
class MenuCategory {
/**
* #var \Company\Entity\Menu
*
* #ORM\ManyToOne(targetEntity="Company\Entity\Menu", inversedBy="categories")
* #ORM\JoinColumn(nullable=false)
*/
protected $menu;
}
class MenuRepository extends EntityRepository implements MenuRepositoryInterface {
public function findById($id, $hydration = Query::HYDRATE_OBJECT) {
$queryBuilder = $this->createQueryBuilder('menu')
->leftJoin('menu.categories', 'categories')
->where('menu.id = :menuId')
->setParameter('menuId', $id);
return $queryBuilder->getQuery()->getSingleResult($hydration);
}
}
The result looks like that:
array(4) {
["id"]=>int(1)
["name"]=> string(6) "Test"
}
I have followed the example here doctrine 2 documentation and made the entity
<?php
namespace Account\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Zend\Filter\Null;
/**
* #ORM\Entity
* #ORM\Table(name="accounts")
*/
class Account
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
* #ORM\Column(length=11)
*/
private $id;
// ......
/**
* #ORM\ManyToMany(targetEntity="Account\Entity\Account", mappedBy="following")
*/
private $followers;
/**
* #ORM\ManyToMany(targetEntity="Account\Entity\Account", inversedBy="followers")
* #ORM\JoinTable(name="followers",
* joinColumns={#ORM\JoinColumn(name="account_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="follower_id", referencedColumnName="id")}
* )
*/
private $following;
public function __construct(){
$this->followers = new ArrayCollection();
$this->following = new ArrayCollection();
}
/**
* #param mixed $followers
*/
public function setFollowers($followers)
{
$this->followers[] = $followers;
}
/**
* #return mixed
*/
public function getFollowers()
{
return $this->followers;
}
public function addFollowers($followers){
foreach($followers as $follower)
$this->followers->add($follower);
}
public function removeFollowers($followers){
$this->followers->removeElement($followers);
}
/**
* #param mixed $following
*/
public function setFollowing($following)
{
$this->following[] = $following;
}
/**
* #return mixed
*/
public function getFollowing()
{
return $this->following;
}
public function addFollowing($followers){
foreach($followers as $follower)
$this->following->add($follower);
}
public function removeFollowing($followers){
$this->following->removeElement($followers);
}
/**
* #param mixed $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
}
So I have 2 accounts (ids 1 and 2) and made it so that 1 follows (is friend to) 2.
The column is something like
user_id follower_id
2 1
By using the following code, I'm not getting any results as I should
$user = $this->entityManager()->getRepository('Account/Entity/Account')->find(1);
$followers = $user->getFollowers();
var_dump($followers);
It returns something like:
object(Doctrine\ORM\PersistentCollection)#357 (9) { ["snapshot":"Doctrine\ORM\PersistentCollection":private]=> array(0) { } ["owner":"Doctrine\ORM\PersistentCollection":private]=> NULL ["association":"Doctrine\ORM\PersistentCollection":private]=> NULL ["em":"Doctrine\ORM\PersistentCollection":private]=> NULL ["backRefFieldName":"Doctrine\ORM\PersistentCollection":private]=> NULL ["typeClass":"Doctrine\ORM\PersistentCollection":private]=> NULL ["isDirty":"Doctrine\ORM\PersistentCollection":private]=> bool(false) ["initialized":"Doctrine\ORM\PersistentCollection":private]=> bool(false) ["coll":"Doctrine\ORM\PersistentCollection":private]=> object(Doctrine\Common\Collections\ArrayCollection)#358 (1) { ["_elements":"Doctrine\Common\Collections\ArrayCollection":private]=> array(0) { } } }
The same happens if I use getFollowing and all the combinations I've tried. Am I missing something? I mean it's pretty much like the documentation code, please help me out!
I'm using Zend Framework 2, if that's of any help.
All associations are LAZY by default, which means it is populated when you first access it. PersistentCollection actually is an iterator and a var_dump will not trigger iteration, that's why you see _intialized property set to false and the count of _elements is 0.
You can use getArrayCopy or simply iterate through the collection.
var_dump($followers->getArrayCopy());
or:
foreach ($followers as $follower) {
var_dump($follower);
}