Sto utilizzando bootable model trait per registrare determinati eventi per i modelli utilizzando il mio tratto. Tuttavia, ho riscontrato un problema nel tentativo di simulare modelli che utilizzano il tratto. In particolare, quando viene creata un'istanza di una versione di Mockery del modello, il suo codice di avvio concorda sul fatto che dovrebbe avere un metodo bootMyTrait, ma non può trovarlo quando tenta di chiamarlo.Problema di un tratto del modello avviabile di Laravel
Sample Repository per il seguito, con comandi da riprodurre.
A titolo di esempio, ecco un tratto:
namespace App;
trait MyTrait
{
public static function bootMyTrait()
{
print("Booting MyTrait\n");
}
}
e un modello di utilizzo:
namespace App;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
use MyTrait;
}
Instantiating il modello funziona regolarmente bene. Questo mostra il risultato desiderato:
$model = new MyModel();
Tuttavia, cercando di deridere questo modello non coopera. Questo:
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*
* @return void
*/
public function testTraitBooting()
{
$model = $this->getMock('App\MyModel');
}
}
Fails. Adding some debugging to Eloquent:
/**
* Boot all of the bootable traits on the model.
*
* @return void
*/
protected static function bootTraits()
{
$class = static::class;
foreach (class_uses_recursive($class) as $trait) {
print("\nTesting that class: $class has method: " . $method = 'boot'.class_basename($trait) . " because of Trait: $trait\n");
if (method_exists($class, $method = 'boot'.class_basename($trait))) {
print("Class: $class has method: $method \n");
try {
forward_static_call([$class, $method]);
} catch (\PHPUnit_Framework_MockObject_BadMethodCallException $e) {
print("Class: $class failed calling $method\n");
throw $e;
}
}
}
}
ci dà questo fallimento:
PHPUnit 5.1.0 by Sebastian Bergmann and contributors.
E 1/1 (100%)
Testing that class: Mock_MyModel_9ee820db has method: bootMyTrait because of Trait: App\MyTrait
Class: Mock_MyModel_9ee820db has method: bootMyTrait
Class: Mock_MyModel_9ee820db failed calling bootMyTrait
Time: 129 ms, Memory: 18.00Mb
There was 1 error:
1) ExampleTest::testTraitBooting
PHPUnit_Framework_MockObject_BadMethodCallException:
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:326
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:309
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:296
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:277
mock-bootable-laravel-model-trait/tests/ExampleTest.php:16
ho provato anche creare modello diversi modi. Utilizzando DatabaseSoftDeletingTraitTest come esempio:
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mockery as m;
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*
* @return void
*/
public function testTraitBooting()
{
$mock = m::mock('App\MyModel');
$mock->shouldReceive('bootMyTrait')->once();
}
}
Ma qui, bootMyTrait non viene mai chiamato:
PHPUnit 5.1.0 by Sebastian Bergmann and contributors.
E 1/1 (100%)
Time: 149 ms, Memory: 19.25Mb
There was 1 error:
1) ExampleTest::testTraitBooting
Mockery\Exception\InvalidCountException: Method bootMyTrait() from Mockery_0_App_MyModel should be called
exactly 1 times but called 0 times.
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php:37
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Expectation.php:271
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php:120
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:297
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:282
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery.php:142
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:122
Quindi, posso spostare il codice che sto facendo nel metodo di avvio a un ServiceProvider, ma poi ho Avrai bisogno di registrare ogni modello che usa il tratto. Questo sembra sporco e l'uso del metodo di avvio sembra appropriato. Quindi penso di aver colto un bug o di aver simulato in modo errato il trait-using-model. Ho guardato allo getMockForTrait
ma ho anche bisogno dell'istanza fittizia per estendere Eloquent (alcuni dei metodi del metodo chiamano metodi eloquenti)
Se qualcuno vede qualcosa che mi è sfuggito (o se mi sto avvicinando totalmente a questo nel modo sbagliato) , molto apprezzato
Grazie! Non sono sicuro del motivo per cui questo non funziona con il wrapper Mockery di Laravel, ma lo prendo io! – timbroder