Laravel 5' assertReponseOk'我使用Mockery时失败(得到500错误)

时间:2015-02-26 19:58:12

标签: php unit-testing laravel-5 mockery

我试图用嘲弄来编写单元测试并且它正在工作。但是,有一件事是行不通的。

我已经找了好几天的答案,但我找不到任何东西,所以这就是问题所在。首先,我将提供一个摘要版本,然后是所有代码。

这不起作用:

public function testIndexCallsRepository()
{
    $mock = Mockery::mock('App\Repositories\Movie\IMovieRepository');

    $mock->shouldReceive('getAll')->once();
    $mock->shouldReceive('getGenres')->once();
    $mock->shouldReceive('getCountries')->once();
    $mock->shouldReceive('getFormats')->once();
    $mock->shouldReceive('getEncodigs')->once();
    $mock->shouldReceive('getUbications')->once();

    App::instance('App\Repositories\Movie\IMovieRepository', $mock);

    $response = $this->call('GET', 'movies');

    $this->assertResponseOk();
}

运行phpunit时,最后一行代码给出了这个错误:

Expected status code 200, got 500

模拟类和断言方法(shouldReceive_s)工作正常。我通过调用坏方法或从控制器中删除调用来检查它,虽然模拟在响应错误时似乎没有任何效果,因为我只得到响应错误。

如果我删除了模拟代码,只留下响应,可行(我的状态代码为200而不是500),所以我必须丢失东西。

我一直关注一些关于嘲笑的文章,其中包括嘲笑后的两个响应行

$this->call('GET', 'movies');
$this->assertResponseOk();

所以它似乎是非常基本的东西,没有问题。我引用的其中一篇文章是http://code.tutsplus.com/tutorials/testing-laravel-controllers--net-31456

我也尝试过:

  • 撰写' $ this-> app-> instance'而不是' App :: instance'把它放在' shouldReceive_s'之前没有效果。
  • 包括父母:: tearDown'在tearDown方法中。

有什么猜测?怎么了?

顺便说一句,我目前正在进行解决方案:

  • 我在没有检查“assertResponseOk”的情况下进行了模拟测试,并检查了模拟是否正如我之前所说的那样。
  • 我有另一种检查响应的方法,如果视图正在获取数据等,而不使用模拟。

这里是完整的'代码失败。我还没有包含存储库代码。它工作正常,视图正确显示数据。

测试代码:

class MovieControllerTest extends TestCase {

    public function setUp()
    {
        parent::setUp();
    }

    public function tearDown()
    {
        Mockery::close();
    }

    public function testIndexCallsRepository()
    {
        $mock = Mockery::mock('App\Repositories\Movie\IMovieRepository');

        $mock->shouldReceive('getAll')->once();
        $mock->shouldReceive('getGenres')->once();
        $mock->shouldReceive('getCountries')->once();
        $mock->shouldReceive('getFormats')->once();
        $mock->shouldReceive('getEncodigs')->once();
        $mock->shouldReceive('getUbications')->once();

        App::instance('App\Repositories\Movie\IMovieRepository', $mock);

        $response = $this->call('GET', 'movies');

        $this->assertResponseOk();
    }

    public function testIndexResponseIsOkAndViewHasAllTheData()
    {
        $response = $this->call('GET', 'movies');

        $this->assertResponseOk();

        $this->assertViewHas('movies');
        $this->assertViewHas('genre_options');
        $this->assertViewHas('country_options');
        $this->assertViewHas('format_options');
        $this->assertViewHas('encoding_options');
        $this->assertViewHas('ubication_options');

        $movies     = $response->original->getData()['movies'];
        $genres     = $response->original->getData()['genre_options'];
        $countries  = $response->original->getData()['country_options'];
        $formats    = $response->original->getData()['format_options'];
        $encodings  = $response->original->getData()['encoding_options'];
        $ubications = $response->original->getData()['ubication_options'];

        $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', 
            $movies);
        $this->assertInternalType('array', $genres);
        $this->assertInternalType('array', $countries);
        $this->assertInternalType('array', $formats);
        $this->assertInternalType('array', $encodings);
        $this->assertInternalType('array', $ubications); 
    }
}

控制器代码:

<?php namespace App\Http\Controllers;

use App\Repositories\Movie\IMovieRepository;

class MovieController extends Controller {

    protected $movie;

    public function __construct(IMovieRepository $movie)
    {
        $this->movie = $movie;
    }

    public function index()
    {
        $data['movies']            = $this->movie->getAll();
        $data['genre_options']     = $this->movie->getGenres();
        $data['country_options']   = $this->movie->getCountries();
        $data['format_options']    = $this->movie->getFormats();
        $data['encoding_options']  = $this->movie->getEncodings();
        $data['ubication_options'] = $this->movie->getUbications();

        return view('movies.index', $data);
    }
}

路线:

Route::get('movies', 'MovieController@index');

2 个答案:

答案 0 :(得分:0)

我相信每个模拟应至少返回一个空数组,否则你将为数组赋值null。

答案 1 :(得分:0)

如果没有您的视图代码,我无法确定,但是,我很确定您的代码是否已损坏,因为您的movies.index视图要求某些$data数组键不能是空的。我会建议以下之一:

Circumvent View逻辑

public function testIndexCallsRepository()
{
    $mock = Mockery::mock('App\Repositories\Movie\IMovieRepository');

    $mock->shouldReceive('getAll')->once()->andReturn('all');
    $mock->shouldReceive('getGenres')->once()->andReturn('genres');
    $mock->shouldReceive('getCountries')->once()->andReturn('countries');
    $mock->shouldReceive('getFormats')->once()->andReturn('formats');
    $mock->shouldReceive('getEncodigs')->once()->andReturn('encodings');
    $mock->shouldReceive('getUbications')->once()->andReturn('ubications');

    App::instance('App\Repositories\Movie\IMovieRepository', $mock);

    $expectedViewData = array(
         'movies' => 'movies',
         'genre_options' => 'genres',
         'country_options' => 'countries',
         'format_options' => 'formats',
         'encoding_options' => 'encodings',
         'ubication_options' => 'ubications',
    );

    View::shouldReceive('make')->once()->with('movies.index', $expectedViewData)->andReturn('compiled view'); 

    $response = $this->call('GET', 'movies');

    $this->assertResponseOk();
}

来自存储库

的模拟响应
public function testIndexCallsRepository()
{
    $mock = Mockery::mock('App\Repositories\Movie\IMovieRepository');

    $mock->shouldReceive('getAll')->once()->andReturn(array('all'));
    $mock->shouldReceive('getGenres')->once()->andReturn(array('genres'));
    $mock->shouldReceive('getCountries')->once()->andReturn(array('countries'));
    $mock->shouldReceive('getFormats')->once()->andReturn(array('formats'));
    $mock->shouldReceive('getEncodigs')->once()->andReturn(array('encodings'));
    $mock->shouldReceive('getUbications')->once()->andReturn(array('ubications'));

    App::instance('App\Repositories\Movie\IMovieRepository', $mock);

    $response = $this->call('GET', 'movies');

    $this->assertResponseOk();
}

以上代码未经过测试,但您应该明白这一点。