2014-11-03 8 views
8

Mam coś jak następuje skonfigurować w laravel:klas ramowe laravel niedostępne w PHPUnit dostawcy danych

W /app/controllers/MyController.php:

class MyController extends BaseController { 

    const MAX_FILE_SIZE = 10000; 

    // .... 

} 

W /app/tests/MyControllerTest.php:

class MyControllerTest extends TestCase { 

    public function myDataProvider() { 
     return [ 
      [ MyController::MAX_FILE_SIZE ] 
     ]; 
    } 

    /** 
    * @dataProvider myDataProvider 
    */ 
    public function testMyController($a) { 
     // Just an example 
     $this->assertTrue(1 == 1); 
    } 
} 

Jednak po uruchomieniu vendor/bin/phpunit I ge t następujący błąd:

 
PHP Fatal error: Class 'Controller' not found in /home/me/my-app/app/controllers/BaseController.php on line 3 

Fatal error: Class 'Controller' not found in /home/me/my-app/app/controllers/BaseController.php on line 3 

Jeśli usunąć odniesienie do klasy MyController w myDataProvider() i zastąpić go dosłownym stałą następnie test zakończy się pomyślnie.

Ponadto mogę umieścić odniesienia do MyController::MAX_FILE_SIZE wewnątrz rzeczywistej metody testMyController(), a test również zostanie pomyślnie zakończony.

Wydaje się, że konfiguracja autoloading dla klas ramowych laravel nie jest ustawiona aż po metoda dostawca danych jest powołanych, lecz przed rzeczywiste metody badań są nazywane. Czy jest jakiś sposób obejścia tego, aby uzyskać dostęp do klas ramowych Laravel z dostawcą danych PHPUnit?


UWAGA: Dzwonię PHPUnit bezpośrednio z linii poleceń, a nie z poziomu IDE (takie jak NetBeans). Wiem, że niektórzy ludzie mieli z tym problemy, ale nie sądzę, że dotyczy to mojego problemu.

Odpowiedz

11

Zgodnie z domniemaniem this answer wydaje się, że jest to związane z kolejnością, w jakiej PHPUnit będzie wywoływać dowolnych dostawców danych i metodę setUp() w dowolnych przypadkach testowych.

PHPUnit zadzwoni do metody dostawcy danych przed przeprowadzeniem jakichkolwiek testów. Przed każdym testem będzie również wywoływać metodę setUp() w teście. Laravel podłącza się do metody setUp(), aby wywołać $this->createApplication(), która doda klasy kontrolerów do "ścieżki włączania", aby umożliwić ich automatyczne ładowanie.

Ponieważ metody dostawcy danych są uruchamiane przed tym zdarzeniem, wszelkie odwołania do klas kontrolera w dostawcy danych kończą się niepowodzeniem. Jest to możliwe to obejść modyfikując klasę testową, aby coś takiego:

class MyControllerTest extends TestCase { 

    public function __construct($name = null, array $data = array(), $dataName = '') { 
     parent::__construct($name, $data, $dataName); 

     $this->createApplication(); 
    } 

    public function myDataProvider() { 
     return [ 
      [ MyController::MAX_FILE_SIZE ] 
     ]; 
    } 

    /** 
    * @dataProvider myDataProvider 
    */ 
    public function testMyController($a) { 
     // Just an example 
     $this->assertTrue(1 == 1); 
    } 
} 

Wywoła createApplication() przed metodami dostawcy danych są prowadzone, a więc nie jest ważne wystąpienie aplikacji, która pozwoli na odpowiednie zajęcia się poprawnie załadowane.

Wydaje się to działać, ale nie jestem pewien, czy jest to najlepsze rozwiązanie, czy też może spowodować jakiekolwiek problemy (chociaż nie mogę wymyślić żadnych powodów, dla których powinien).

+2

Prawdopodobnie bezpieczniej jest wywołać '$ this-> refreshApplication();', ponieważ to ustawia także środowisko na 'testing'. Nie musisz też tworzyć konstruktora, możesz po prostu wywołać '$ this-> refreshApplication();' bezpośrednio w twoim dostawcy danych (jeśli tylko masz taki, który myślę). – Antonio

4

Test zostanie zainicjowany znacznie szybciej, jeśli utworzysz aplikację bezpośrednio w metodzie dataProvider, szczególnie jeśli masz duży zestaw elementów do przetestowania.

public function myDataProvider() { 
    $this->createApplication(); 

    return [ 
     [ MyController::MAX_FILE_SIZE ] 
    ]; 
}