Class 'Eloquent' not found when mocking in Laravel - laravel

I'm following through Jeffrey Way's Laravel Testing Decoded and I've hit an issue I can't seem to fix.
I'm actually work through this tutorial: http://net.tutsplus.com/tutorials/php/testing-laravel-controllers/ Which is an excerpt from his book.
Basically I have a test like so:
class PostsTest extends TestCase {
public function __construct()
{
$this->mock = Mockery::mock('Eloquent', 'Post');
}
And that like for mocking Eloquent and Post returns:
PHP Fatal error: Class 'Eloquent' not found
When I run phpunit. Incidentally if I use Jeffrey's Laravel Generators and just generate some scaffold e.g.
php artisan generate:scaffold post --fields="title:string, body:string"
And run phpunit I get same error. He's using the same:
$this->mock = Mockery::mock('Eloquent', 'Post');
To mock the classes. Does anyone have any suggestions on what the issue could be?
I've been working through the tutorial again from scratch and am still getting the same error. I've pushed it to a public repo so people can see: https://github.com/RyanHavoc/tdd-laravel
Just pull it down, run composer install/update and phpunit.

I found a solution to the issue.
//Causes the Class 'Eloquent' not found error
public function __construct()
{
$this->mock = Mockery::mock('Eloquent', 'Post');
}
//Setting the mocks in the setUp() method instead works
public function setUp()
{
parent::setUp();
$this->mock = Mockery::mock('Eloquent', 'Post');
}

Related

Laravel unit testing assert functions always failing

I have created a very basic unit testing class under Laravel root-->tests-->Unit-->SimpleTest.php
Inside the file i have import the controller class that i need to test. And test function is like this.
class SimpleTest extends TestCase
{
public function testLoadUsers()
{
$controller_obj = new UsersController;
$data_status = $controller_obj->load_users();
if($data_status != null){
$this->assertTrue(true);
}
else{
$this->assertTrue(false);
}
}
}
I executed this test case in Artisan console like this,
php vendor/phpunit/phpunit/phpunit tests/Unit/SimpleTest.php
Always this fails. My controller function returning data as well without an issue. I tested without defining any condition and just,
$this->assertTrue(true);
Then it works. So i assume there is no any issue with the phpunit test command as well.
I'm sorry, this is not a direct answer.
I think maybe you should check the value of $data_status by this.
class SimpleTest extends TestCase
{
public function testLoadUsers()
{
$controller_obj = new UsersController;
$data_status = $controller_obj->load_users();
$this->expectOutputString('Array');
print data_status;
}
}

How to mock only one method with Laravel using PhpUnit

I have this test :
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Services\AccessTokenService;
use App\Services\MemberService;
class BranchTest extends TestCase
public function testPostBranchWithoutErrors()
{
$this->mock(AccessTokenService::class, function ($mock) {
$mock->shouldReceive('introspectToken')->andReturn('introspection OK');
});
$this->mock(MemberService::class, function ($mock) {
$mock->shouldReceive('getMemberRolesFromLdap')->andReturn(self::MOCKED_ROLES);
});
As you see, there are 2 mocks on this test. The 2nd one 'MemberService:class' is my current problem. In this class there are 2 functions : 'createMember' and 'getMemberRolesFromLdap'. I precise that I want to mock only the 'getMemberRolesFromLdap' function.
In the documentation, it is written :
You may use the partialMock method when you only need to mock a few methods of an object. The methods that are not mocked will be executed normally when called:
$this->partialMock(Service::class, function ($mock) {
$mock->shouldReceive('process')->once();
});
But when I use "partialMock", I have this error:
Error: Call to undefined method Tests\Feature\BranchTest::partialMock()
And when I try a classic mock (no partial), I have this error:
Received Mockery_1_App_Services_MemberService::createMember(), but no expectations were specified
certainly because there are 2 functions in this class and so PhpUnit does not know what to do with the function 'createMember'.
What can I try next? I am a beginner to PhpUnit tests.
Edit
Laravel 6.0
PhpUnit 7.5
PartialMock shorthand is firstly added in Laravel 6.2 see the release notes. So an upgrade to 6.2 should fix your problem.
Secondly you can add the following snippet to your Tests\TestCase.php class and it should work.
protected function partialMock($abstract, Closure $mock = null)
{
return $this->instance($abstract, Mockery::mock(...array_filter(func_get_args()))->makePartial());
}

Call to a member function connection() on null Laravel 5.4

Try write a unit test and i need do sql query
class UpdateThrowsTest extends TestCase
{
protected $bgame;
protected $game_id = 95;
public function setUp(){
$game = new Game();
$game = $game::find($this->game_id);
}
}
and then i write "phpunit" in console and try exception
Call to a member function connection() on null.
If anyone bounce to this error during test with Laravel 6 project.
Try to check if the extends TestCase is using the right TestCase.
It could be due to Laravel 6 make:test generated test using the wrong TestCase.
Change
use PHPUnit\Framework\TestCase;
To
use Tests\TestCase;
The problem should solve.
I had this error on laravel 7 (nothing worked even php artisan serve) and fixed it with
composer dumpautoload
Before that update my vendor with composer update and then everything worked fine.

Laravel integration test throwing spurious 404 error when run as a class, individual tests work fine

I'm using the new integration testing stuff in L5.1. I'm getting some strange errors when running a test class - mostly 404's on the pages I'm testing. Oddly, when I filter down to an individual test the test passes fine. When I run the whole test class or test suite that it's a part of, it fails with a 404. The route works in the browser, and the test passes when I run by itself, so it's clearly not a valid error.
The code looks something like this:
class MyTest extends \TestCase
{
use WithoutMiddleware;
public function __construct() {
parent::__construct();
$this->mock = m::mock('MyApp\Stuff\Repository');
$this->validator = m::mock('Illuminate\Validation\Factory');
$this->mockedClass = m::mock('MyApp\Stuff\Service');
}
/**
* #test
*/
public function it_should_get_all_thingies() {
$this->mockedClass->shouldReceive('someMethod')
->once()
->andReturn('yay');
$this->app->instance('MyApp\Stuff\Service', $this->mockedClass);
$this->visit('/api/v1/thingies');
}
}
When I run
phpunit --filter=it_should_get_all_thingies , it works fine.
When I run
phpunit --filter=MyTest, it dies with a 404. I can copy the relevant URL from the error message into the browser and it works fine.
The only other relevant fact that I can think of is that this on an updade from L4.2 to 5.0 to 5.1.
Any help is greatly appreciated.
Figured out what was triggering the error and how to work around it. I was pulling in a secondary routes file like this:
Route::get('/', function () {
return view('welcome');
});
Route::group(['prefix' => 'api/v1'], function() {
require_once_app_path(__DIR__ . '/routes2.php');
});
The require_once_app_path triggers the issue. Didn't happen in L4.2 or L5.0, started when we upgraded to 5.1. Replacing that with require seems to sort things out.

Laravel 4 model unit test with Codeception - Class 'Eloquent' not found

I'm trying to use Codeception to run my Laravel 4 unit tests.
Running a test for a simple class with no dependencies works fine. But when I instantiate a model which depends on Eloquent, I get this fatal error:
PHP Fatal error: Class 'Eloquent' not found in /var/www/project/app/models/Role.php on line 4
Unit test:
<?php
use Codeception\Util\Stub;
class TestModel extends \Codeception\TestCase\Test
{
public function testExample()
{
$role = new Role;
$role->name = 'superuser';
$this->assertEquals('superuser', $role->name);
}
}
Model:
<?php
class Role extends Eloquent
{
public function users()
{
return $this->belongsToMany('User');
}
}
Project structure:
I'm running vendor/bin/codecept run unit from the project root, with this file structure:
/project
codeception.yml
/vendor/bin/codecept
/app
/tests
unit.suite.yml
/unit
ExampleTest.php
/models
Role.php
...etc
What am I doing wrong?
By looking at the Codeception L4 sample app, I was able to see how to bootstrap the autoload to resolve this issue, by adding these lines to project/app/tests/_boostrap.php:
include __DIR__.'/../../vendor/autoload.php';
$app = require_once __DIR__.'/../../bootstrap/start.php';
\Codeception\Util\Autoload::registerSuffix('Page', __DIR__.DIRECTORY_SEPARATOR.'_pages');
Edit: when upgrading from Laravel 4.0 to 4.1, it is also necessary to add an extra line:
$app->boot();
I'm probably late to the party, but if you don't need the codecept stuff. You should be extending laravel's implementation of PHPUnit_Framework_TestCase called just TestCase. Like this:
class TestModel extends TestCase {
}
The answer to this question is a little outdated now. With Laravel 5 I got the same error (Class 'Eloquent' not found...) and solved it by copying the code from Laravels base TestCase.php file. This file is used for testing within the Laravel framework (NOT using codeception).
To fix the 'Eloquent not found' error, add the following lines to project/tests/unit/_bootstrap.php
<?php
$app = require __DIR__.'/../../bootstrap/app.php';
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
Honestly I'm not sure why it works, but it does! I'll edit if I figure out why or someone comments.
The Eloquent class cannot be found when you are running your unit tests.
Try adding use Illuminate\Database\Eloquent\Model as Eloquent; to Role.php.
You can go to TestCase class and override method refreshApplication (add method to TestCase) with adding auth or some:
protected function refreshApplication()
{
$this->app = $this->createApplication();
$this->client = $this->createClient();
$this->app->setRequestForConsoleEnvironment();
$this->app->boot();
// authenticate your user here, when app is ready
$user = new User(array('username' => 'John', 'password' => 'test'));
$this->be($user);
}
I solved a similar problem with Laravel 4 and Codeception by adding the following lines to _bootstrap.php
$app = require __DIR__.'/../../bootstrap/start.php';
$app->boot();
Hope this helps a fellow googler!

Resources