Testsimulator Mocking


Testsimulator

    Einführung
  • Simulationsobjekt
  • Aufgabensimulation
  • Ereignissimulation
    • Umfangreich Ereignissimulation
  • E-Mail-Simulation
  • Benachrichtigungssimulation
  • Warteschlangensimulation
  • Speicherung Simulation
  • Fassaden

Einführung

Beim Testen einer Laravel-Anwendung möchten Sie möglicherweise das Verhalten bestimmter Funktionen Ihrer Anwendung „simulieren“ und so verhindern, dass dieser Teil tatsächlich im Test ausgeführt wird. Beispiel: Während der Ausführung des Controllers wird ein Ereignis (Event) ausgelöst, wodurch verhindert wird, dass das Ereignis beim Testen des Controllers tatsächlich ausgeführt wird. Dadurch können Sie nur die HTTP-Antwort des Controllers testen, ohne sich Gedanken über das Auslösen von Ereignissen machen zu müssen. Natürlich können Sie diese Ereignislogik auch in einem separaten Test testen.

Laravel bietet sofort einsatzbereite Hilfsfunktionen für die Simulation von Ereignissen, Aufgaben und Fassaden. Diese Funktionen basieren auf Mocker und sind sehr bequem zu verwenden. Es ist nicht erforderlich, komplexe Mockery-Funktionen manuell aufzurufen. Natürlich können Sie auch Mockery oder PHPUnit verwenden, um Ihren eigenen Emulator zu erstellen.

Mock Object

Wenn Sie ein Objekt verspotten, das über den Service-Container von Laravel in Ihre Anwendung eingefügt wird, werden Sie dies tun Die Scheininstanz muss als instance in den Container eingebunden werden. Dadurch wird der Container angewiesen, eine Scheininstanz des Objekts zu verwenden, anstatt das reale Objekt zu erstellen:

use Mockery;
use App\Service;
$this->instance(Service::class, Mockery::mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
   })
);

Um den obigen Prozess komfortabler zu gestalten, können Sie die bereitgestellte grundlegende Testfallklasse von Laravel verwenden mock Methode:

use App\Service;$this->mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
 });

Aufgabensimulation

Alternativ zur Simulation können Sie die BusFassaden< verwenden 🎜> Methode, um zu verhindern, dass Aufgaben tatsächlich zur Ausführung verteilt werden. Bei Verwendung von Fake erscheinen im Allgemeinen Behauptungen hinter dem Testcode: fake

<?php
    namespace Tests\Feature;
    use Tests\TestCase;use App\Jobs\ShipOrder;
    use Illuminate\Support\Facades\Bus;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class ExampleTest extends TestCase{
        public function testOrderShipping()
            {   
                 Bus::fake();        
                 // 执行订单发货...        
                 Bus::assertDispatched(ShipOrder::class, function ($job) use ($order) { 
                            return $job->order->id === $order->id;      
                             });       
                  // 断言任务并未分发...        
                  Bus::assertNotDispatched(AnotherJob::class);   
                }
           }

Ereignissimulation

als Mock Als an Alternativ können Sie die

Fassade des Event nutzen Methode zum Simulieren des Ereignis-Listeners. Der Ereignis-Listener wird während des Tests nicht tatsächlich ausgelöst. Anschließend können Sie die laufenden Assertion-Ereignisse testen und sogar die empfangenen Daten überprüfen. Bei Verwendung von Fake erscheinen im Allgemeinen Behauptungen hinter dem Testcode: fake

<?php
    namespace Tests\Feature;
    use Tests\TestCase;use App\Events\OrderShipped;
    use App\Events\OrderFailedToShip;
    use Illuminate\Support\Facades\Event;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class ExampleTest extends TestCase{   
     /**
     * 测试订单发送
     */   
      public function testOrderShipping() 
         {   
              Event::fake();        
              // 执行订单发送...        
              Event::assertDispatched(OrderShipped::class, function ($e) use ($order) {  
                        return $e->order->id === $order->id;    
                     });        
               // 断言一个事件被发送了两次...   
              Event::assertDispatched(OrderShipped::class, 2);        
              // 未分配断言事件...        
              Event::assertNotDispatched(OrderFailedToShip::class);   
            }
        }

{note} Die Ereignisüberwachung wird nach dem Aufruf von

nicht ausgeführt. Daher müssen Ihre ereignisbasierten Tests das Fabrikmodell verwenden. Um beispielsweise eine UUID im Event::fake()-Ereignis des Modells zu erstellen, sollten Sie creating nach Event::fake() aufrufen, um das Fabrikmodell zu verwenden.

Simulieren einer Teilmenge von Ereignissen

Wenn Sie Ereignis-Listener nur für eine bestimmte Menge von Ereignissen simulieren möchten, können Sie diese an

oder übergeben fake Methoden: fakeFor

/**
 * 测试订单流程
 */
 public function testOrderProcess(){ 
    Event::fake([   
         OrderCreated::class,   
         ]);    
    $order = factory(Order::class)->create();    
    Event::assertDispatched(OrderCreated::class);    
   // 其他事件照常发送...    
  $order->update([...]);
 }

Scoped Event Simulation

Wenn Sie Event Listening nur für einen Teil des Tests simulieren möchten, Sie können

verwenden Methode: fakeFor

<?php
    namespace Tests\Feature;
    use App\Order;use Tests\TestCase;
    use App\Events\OrderCreated;
    use Illuminate\Support\Facades\Event;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class ExampleTest extends TestCase{   
     /**
     * 测试订单流程
     */   
     public function testOrderProcess()   
      {     
         $order = Event::fakeFor(function () { 
                    $order = factory(Order::class)->create();            
                    Event::assertDispatched(OrderCreated::class);            
                    return $order;        
             });       
           // 事件按正常方式发送,观察者将运行...       
          $order->update([...]);    
        }
      }

E-Mail-Simulation

Sie können die Mail-Methode von fakeFacade verwenden, um den E-Mail-Versand während des Tests zu simulieren. Dann können Sie behaupten, dass die Mailings an gesendet werden Benutzer, oder überprüfen Sie sogar, was sie erhalten haben. Bei der Verwendung von Fakes werden Assertions im Allgemeinen nach dem Testcode platziert:

<?php
    namespace Tests\Feature;
    use Tests\TestCase;use App\Mail\OrderShipped;
    use Illuminate\Support\Facades\Mail;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class ExampleTest extends TestCase{ 
       public function testOrderShipping()  
         {     
            Mail::fake();        
            // 断言没有发送任何邮件...        
            Mail::assertNothingSent();        
            // 执行订单发送...        
            Mail::assertSent(OrderShipped::class, function ($mail) use ($order) {  
                      return $mail->order->id === $order->id;       
                   });        
           // 断言一条发送给用户的消息...        
           Mail::assertSent(OrderShipped::class, function ($mail) use ($user) { 
                      return $mail->hasTo($user->email) &&                   
                      $mail->hasCc('...') &&                   
                      $mail->hasBcc('...');     
                   });        
             // 断言邮件被发送两次...     
           Mail::assertSent(OrderShipped::class, 2);       
           // 断言没有发送邮件...        
           Mail::assertNotSent(AnotherMailable::class);   
           }
        }

Wenn Sie eine Hintergrundaufgabe zum Ausführen der E-Mail-Versandwarteschlange verwenden, sollten Sie assertQueued anstelle von assertSent verwenden :

Mail::assertQueued(...);
Mail::assertNotQueued(...);

Benachrichtigungssimulation

Sie können die Notification-Methode von Facade verwenden, um Benachrichtigungen zu simulieren , wird während des Tests tatsächlich keine Benachrichtigung gesendet. Sie können dann behaupten, dass Benachrichtigungen an den Benutzer gesendet wurden, und sogar überprüfen, was er erhalten hat. Bei der Verwendung von Fakes werden Assertions im Allgemeinen nach dem Testcode platziert: fake

<?php
    namespace Tests\Feature;
    use Tests\TestCase;
    use App\Notifications\OrderShipped;
    use Illuminate\Support\Facades\Notification;
    use Illuminate\Notifications\AnonymousNotifiable;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class ExampleTest extends TestCase{
        public function testOrderShipping()
            {   
                 Notification::fake();        
                 // 断言没有发送通知...        
                 Notification::assertNothingSent();        
                 // 执行订单发送...        
                 Notification::assertSentTo(          
                   $user,            
                   OrderShipped::class,            
                   function ($notification, $channels) use ($order) {    
                               return $notification->order->id === $order->id;   
                                  }       
                        );       
                   // 断言向给定用户发送了通知...      
                  Notification::assertSentTo(     
                        [$user], OrderShipped::class  
                          );       
                   // 断言没有发送通知...   
                  Notification::assertNotSentTo( 
                        [$user], AnotherNotification::class    
                          );       
                  // 断言通过 Notification::route() 方法发送通知...        
                   Notification::assertSentTo(     
                          new AnonymousNotifiable, OrderShipped::class     
                            );   
                      }
             }

Warteschlangensimulation

Als Simulationsalternative , Sie können die

-Methode von Queue Facade verwenden, um zu vermeiden, dass die Aufgabe tatsächlich zur Ausführung in die Warteschlange gestellt wird. Sie können dann bestätigen, dass Aufgaben in die Warteschlange verschoben wurden, und sogar die empfangenen Daten überprüfen. Bei der Verwendung von Fakes werden Behauptungen im Allgemeinen nach dem Testcode platziert: fake

<?php
    namespace Tests\Feature;
    use Tests\TestCase;use App\Jobs\ShipOrder;
    use Illuminate\Support\Facades\Queue;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class ExampleTest extends TestCase{
        public function testOrderShipping() 
           {   
                Queue::fake();        
                // 断言没有任务被发送...        
                Queue::assertNothingPushed();        
                // 执行订单发送...        
                Queue::assertPushed(ShipOrder::class, function ($job) use ($order) {  
                          return $job->order->id === $order->id;       
                         });        
                // 断言任务进入了指定队列...        
                Queue::assertPushedOn('queue-name', ShipOrder::class); 
                // 断言任务进入2次...        
                  Queue::assertPushed(ShipOrder::class, 2);        
                  // 断言没有一个任务进入队列...        
                  Queue::assertNotPushed(AnotherJob::class);        
                  // 断言任务是由特定的通道发送的...        
                  Queue::assertPushedWithChain(ShipOrder::class, [    
                          AnotherJob::class,            
                          FinalJob::class        
                       ]);  
                   }
               }

Store-Simulation

Sie können < verwenden 🎜> Die

-Methode von Facade kann in Kombination mit UploadedFile problemlos eine simulierte Festplatte generieren Das Tool zur Generierung von Klassendateien vereinfacht das Testen des Datei-Uploads erheblich. Beispiel: Storage

<?php
    namespace Tests\Feature;
    use Tests\TestCase;
    use Illuminate\Http\UploadedFile;
    use Illuminate\Support\Facades\Storage;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class ExampleTest extends TestCase{
        public function testAvatarUpload() 
           {   
                Storage::fake('avatars');        
                $response = $this->json('POST', '/avatar', [ 
                           'avatar' => UploadedFile::fake()->image('avatar.jpg')     
              ]);        
          // 断言文件已存储...        
          Storage::disk('avatars')->assertExists('avatar.jpg');        
          // 断言文件不存在...        
          Storage::disk('avatars')->assertMissing('missing.jpg');   
          }
       }
fake

{tip} Standardmäßig löscht die Methode
alle Dateien im temporären Verzeichnis. Wenn Sie diese Dateien behalten möchten, können Sie „persistentFake“ verwenden.

fake

Fassaden

Im Gegensatz zu herkömmlichen statischen Methodenaufrufen können auch Fassaden simuliert werden. Im Vergleich zu herkömmlichen statischen Methoden bietet es große Vorteile. Selbst wenn Sie die Abhängigkeitsinjektion verwenden, ist die Testbarkeit nicht um die Hälfte schlechter. In Ihren Tests möchten Sie möglicherweise Aufrufe an die Laravel-Fassade in Ihrem Controller simulieren. Zum Beispiel das Verhalten im folgenden Controller:

<?php
    namespace App\Http\Controllers;
    use Illuminate\Support\Facades\Cache;
    class UserController extends Controller{   
     /**
     * 显示应用里所有用户
     *
     * @return Response
     */    
     public function index() 
        {      
          $value = Cache::get('key');      
            //
         }
     }

Wir können die shouldReceive Facade durch die Cache-Methode simulieren, die eine Mockery-Instanz zurückgibt. Da Facade-Aufrufe tatsächlich vom Service-Container von Laravel verwaltet werden, kann Facade eine bessere Testbarkeit aufweisen als herkömmliche statische Klassen. Als Nächstes verspotten wir die Cache-Methode der get Facade:

<?php
    namespace Tests\Feature;
    use Tests\TestCase;
    use Illuminate\Support\Facades\Cache;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class UserControllerTest extends TestCase{ 
       public function testGetIndex()  
         {    
             Cache::shouldReceive('get')              
                   ->once()                    
                   ->with('key')                    
                   ->andReturn('value');        
             $response = $this->get('/users');      
             // ...  
            }
       }

{note} Sie können die Request Facade nicht verspotten. Verwenden Sie stattdessen HTTP-Hilfsfunktionen wie get und post, wenn Sie beim Ausführen Ihrer Tests bestimmte Parameter übergeben müssen. Simulieren Sie in ähnlicher Weise bitte die Config::set-Fassade, indem Sie während des Tests Config aufrufen.

Dieser Artikel wurde zuerst auf der Website LearnKu.com veröffentlicht.