Я пытаюсь использовать насмешку для написания модульных тестов, и это работает. Однако есть одна вещь, которая не работает.
Я искал ответ несколько дней, но ничего не нашел, так что вот в чем дело. Сначала выложу краткую версию, а потом весь код.
Это не работает:
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» без каких-либо эффектов.
- включая 'parent::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');