I have the following model:
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
public static function foo():bool
{
return true;
}
}
And for that I made the following controller:
namespace App\Controler;
use App\Model\Foo;
class MyController
{
public function bar()
{
$value=MyModel::foo();
if($value){
return "OK";
}
throw new \Exception("Foo not true");
}
}
And I want to test my controller:
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use App\Model\MyModel;
use Mockery;
class MyControllerTest extends BaseTestCase
{
public function testBar()
{
$mock=Mockery::mock('alias:'.MyModel::class);
$mock->shouldReceive('foo')->andReturn(false);
/// Rest of thest here
}
}
But once I run my test I get the following error:
PHPUnit 7.5.20 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 1.62 seconds, Memory: 14.00 MB
There was 1 error:
1) Tests\MyControllerTest::testBar
Mockery\Exception\RuntimeException: Could not load mock App\Model\MyModel, class already exists
/var/www/html/vendor/mockery/mockery/library/Mockery/Container.php:226
/var/www/html/vendor/mockery/mockery/library/Mockery.php:118
/var/www/html/tests/MyControllerTest.php:20
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
In order to mitigarte the error as seen in https://stackoverflow.com/a/53266979/4706711 I tried:
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use App\Model\MyModel;
use Mockery;
class MyControllerTest extends BaseTestCase
{
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testBar()
{
$mock=Mockery::mock('alias:'.MyModel::class);
$mock->shouldReceive('foo')->andReturn(false);
/// Rest of thest here
}
}
But still I get the same error.
Based upon the answer of @mohammad.kaab I tried the following:
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use App\Model\MyModel;
use Mockery;
class MyControllerTest extends BaseTestCase
{
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testBar()
{
$this->app->instance(MyModel::class, \Mockery::mock(MyModel::class, function($mock){
$mock->shouldReceive('foo')->andReturn(true);
}));
$myModel = $this->app->make(MyModel::class);
dd($myModel::foo()); // should return true
}
}
Thout it can't work because The \Mockery::mock
mock an instance and does not mock the class itself. Therefore I tried the following:
public function testBar()
{
$mock=Mockery::mock('alias:'.MyModel::class);
$mock->shouldReceive('foo')->andReturn(false);
/// Rest of thest here
}
And did not worked for me.