

以下、手順を実行したとき、エラーが出てしまいます。

（１）Cloud9にて、laravelをインストール。

（２）route.php を route_a.php にコピー。  
route_a.php に以下記述追加

[code]

    Route::get('/test/', function () {
        echo 'test';
    });
    
[/code]

（３）ExampleTest.php を以下のように修正

[code]

    <?php
    
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    use Illuminate\Foundation\Testing\DatabaseMigrations;
    use Illuminate\Foundation\Testing\DatabaseTransactions;
    use Illuminate\Filesystem\Filesystem;
    
    class ExampleTest extends TestCase
    {
        /**
         * A basic functional test example.
         *
         * @return void
         */
        public function testBasicExample()
        {
            $this->editRoute();
    
            $this->visit('/')
                 ->see('Laravel 5');
            $this->visit('https://laravel-cloned-test1-dog-ears.c9users.io/test/');
        }
    
        private function editRoute(){
            $this->files = new Filesystem;
            $this->files->move( './app/Http/routes.php', './app/Http/routes_b.php');
            $this->files->move( './app/Http/routes_a.php', './app/Http/routes.php');
            Artisan::call('clear-compiled');
            Artisan::call('cache:clear');        
        }
    }
    
[/code]

（４）phpunitを実行

[code]

    php ./vendor/bin/phpunit
    
[/code]

すると、下記のようなエラーが出ます。

[code]

    There was 1 failure:
    
    1) ExampleTest::testBasicExample
    A request to [http://localhost/test] failed. Received status code [404].
    
[/code]

エラー後、editRoute()をコメントアウトして、  
ただテストだけをすると、/test/もテストOKが出ます。

※実際には、editRoute()は外部のクラスに持たせるメソッドですが、  
簡略化のため、このような書き方をしています。

どなたか、この問題を解決する方法をご教示願えますでしょうか？  
よろしくお願いいたします。


CC BY-SA 3.0
2016-04-07T05:19:16.530
23810
2023-09-14T12:22:26.920
2023-09-14T12:22:26.920
3060
15072
question
laravel phpunit aws-cloud9
Cloud9にlaravelをインストールしてphpunitテストするとエラーが出る。


Laravelのテスト機能では、各テストメソッドの前に実行される `TestCase::setUp()`
メソッドでLaravelを初期化し、ルーティングなどの設定を読み込んでいます。ですから、テストメソッドで `routes.php`
ファイルを変更しても反映されません。Artisanコマンド `clear-compiled` や `cache:clear`
もファイルに書き出されたキャッシュを削除するだけですから、同じことです。

このため、テストメソッドごとに routes.php を差し換えたいのであれば、`setUp()`
メソッドをオーバーライドして、Laravelが起動する前に行う必要があります。

[code]

    class ExampleTest extends TestCase
    {
        public function setUp()
        {
            $this->editRoute();
    
            //あとは通常通りにLaravelを起動させる
            parent::setUp();
        }
    
        public function testBasicExample()
        {
            $this->visit('/test/');
        }
    
        private function editRoute(){
            // setUp() の時点ではまだLaravelを読み込んでいないので、
            // PHPの標準関数で処理を行う。
    
            rename('./app/Http/routes.php', './app/Http/routes_b.php');
            rename('./app/Http/routes_a.php', './app/Http/routes.php');
    
            // もしartisanを呼び出す必要があればexecを使うとか・・・？
        }
    }
    
[/code]

上のコードでは質問に書かれていたものをそのまま再現しましたが、`setUp()`
は各テストの前に毎回実行されることに注意してください。もしテストケース（クラス）内で一度だけ書き換えればいいというのであれば、
`setUpBeforeClass()` を使う手もあります。

参考 [PHPUnit マニュアル – 第4章
フィクスチャ](https://phpunit.de/manual/current/ja/fixtures.html)

一応、Laravel起動後でも以下のようにすれば routes.php
を再読み込みできるようですが、他に問題が起きないという自信はないです。`setUp()` 内で行ったほうがよいでしょう。

[code]

    public function testBasicExample()
    {
        // 既存のルートを全て削除する
        Route::setRoutes(new \Illuminate\Routing\RouteCollection);
        // 新しいルートを読み込みなおす
        include(app_path('/Http/routes_a.php'));
    
        $this->visit('/test');
    }
    
[/code]

なお `visit()` は内部的なルーティングしか行わないので、URLのホスト名は無視されます。実際エラーメッセージでも `localhost`
に置き換えられていますね。

> エラー後、editRoute()をコメントアウトして、 ただテストだけをすると、/test/もテストOKが出ます。

質問に書かれたテストを一度実行すると routes.php が書き換えられますから、二回目は上手くいくのだと思います。routes.php
を元に戻してからテストすれば、一回目同様エラーになるはずです。


CC BY-SA 3.0
2016-04-07T06:19:17.280
23814
2016-04-07T06:54:19.943
2016-04-07T06:54:19.943
8000
8000
23810
answer