0

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.

Dimitrios Desyllas
  • 9,082
  • 15
  • 74
  • 164
  • `$mock=Mockery->mock(` this part does not look like a valid syntax to me. You either create an instance of the mock or you call a static method? You are also missing a semicolon in the imports. – thefallen May 15 '20 at 10:59
  • I fixed it tyhe typo. – Dimitrios Desyllas May 15 '20 at 11:02
  • Does this answer your question? [Mockery fails with 'Could not load mock ... class already exists' when running with --code-coverage](https://stackoverflow.com/questions/51708289/mockery-fails-with-could-not-load-mock-class-already-exists-when-running-w) – thefallen May 15 '20 at 11:07
  • No I as you can see I tried the and did not worked for me. – Dimitrios Desyllas May 15 '20 at 11:17
  • What about that semicolon when importing `use Mockery` is this missing only here in the question? – thefallen May 15 '20 at 11:18
  • Still I get the error with the semicolymn as well. – Dimitrios Desyllas May 15 '20 at 11:19
  • Bold opinion with how mocking and the container works with Laravel, dont use static methods. What is the reason for that method to be static in the first place? – mrhn May 15 '20 at 23:59

1 Answers1

0

Maybe you can use this code

$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
Mohammad.Kaab
  • 1,025
  • 7
  • 20
  • It does not work for the following reasons: 1. I need an alias and using the aliased approach still does not work. I get the very same error. Also I need to mock a STATIC method I do not want to make an instance of it. – Dimitrios Desyllas May 15 '20 at 14:32