【发布时间】:2015-04-29 08:54:25
【问题描述】:
我正在尝试使用嘲弄来编写单元测试并且它正在工作。但是,有一件事是行不通的。
这几天我一直在寻找答案,但我没有找到任何东西,所以这就是问题所在。首先我会放一个总结版本,然后是所有代码。
这不起作用:
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 方法中包含“parent::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');
【问题讨论】:
标签: php unit-testing laravel-5 mockery