2017-01-05 3 views
1

Das Folgende ist eine vereinfachte Klasse der Steuerung arbeite ich an:Wie verspotten Sie das zum Testen?

class UserController extends Controller { 
    protected $user; 

    public function __construct(User $user) { 
     $this->user = user; 
    } 

    public function contact(ContactFormRequest $request) { 
     $user = $this->user 
      ->where('email', $request->email) 
      ->with(['orders' => function($q) { 
       $q->orderBy('created_at', 'desc') 
        ->first(); 
      }]) 
      ->first(); 

     return view('contact', ['user' => $user]); 
    } 
} 

Dies ist der Testfall habe ich bisher:

class ExampleTest extends TestCase { 
    public function setUp() { 
     $this->mockUser = Mockery::mock(Model::class, User::class); 
     $this->app->instance('User', $this->mockUser); 
    } 

    public function testContactForm() { 
     $this->userMock 
      ->shouldReceive('where') 
      ->once() 
      ->with('email', '[email protected]') 
      ->andReturn(new Collection(new User, new User)); 

     $this->visit('contact-form'); 
    } 
}  

Ich gebe zu, ich dies aus dem Gedächtnis schreibe anstatt den vorhandenen Code vor mir zu haben. Aber dieser Test bei der Arbeit passiert PHPUnit. Das Problem ist, dass der Besuch einen Fehler wirft und ich habe zusätzliche ->see('something') Test muss ich machen.

Ich brauche den Rest des Mocks, der einen vollen und brauchbaren Benutzer vorgibt, den Controller und die Ansicht zu verspotten.

Ich erwarte, dass es in etwa so aussieht (das ist, wo der Code schief geht)

$this->userMock 
    ->shouldReceive('where') 
    ->once() 
    ->with('email', '[email protected]') 
    ->andReturn(new Collection(new User)) 
    ->shouldReceive('with') 
    ->once(); 
    ->with(['orders' => function($q) { 
     $q->orderBy('created_at', 'desc') 
      ->first(); 
     }]) 
    ->andReturn(**something**) 
    ->shouldReceive('first') 
    ->once() 
    ->andReturn(new Collection(new User)); 

Antwort

0

Sie das ORM nicht spotten (weiß als Don't mock third-party libraries oder nur Scheintypen, die Sie besitzen). Stellen Sie stattdessen eine Testdatenbank bereit (entweder mit Fixture oder afactory), so dass der Code tatsächlich den gewünschten Benutzer findet.

+0

Hey Maxim, ich würde sagen, dass Controller-Tests idealerweise nicht die echte Testdatenbank benötigen. Ich würde das ORM innerhalb einer Serviceklasse kapseln und dann dieses im Kontrollertest vortäuschen. Aber für die Service-Schicht-Klasse würde ich genau das tun, was Sie vorgeschlagen haben, und mit einer Test-Datenbank testen, um sicherzustellen, dass die Logik tatsächlich funktioniert .. Wenn es außerhalb des Controllertests ist, könnten mehr Boundary-Tests einfacher hinzugefügt werden. – malte

Verwandte Themen