Интерфейсы Laravel Mocking внутри контроллеров

Я пытаюсь написать несколько модульных тестов для своих контроллеров.

Я реализовал интерфейс и репозиторий, он передается контроллеру через Dependancy Injection.

Я написал модульный тест, который имитирует интерфейс, а New создает экземпляр контроллера.

Мой тест падает со следующей ошибкой

Mockery\Exception\InvalidCountException : Method find(<Any Arguments>) from Mockery_0_App_Interfaces_VenueRepositoryInterface should be called
 exactly 1 times but called 2 times.

В конечном счете, я хочу проверить, когда метод индекса вызывается на контроллере, тогда он правильно взаимодействует с интерфейсом, отсюда и желание издеваться над ним. Я напишу дополнительные тесты, чтобы проверить реализацию интерфейса.

Венуеконтроллертест

<?php

namespace Tests\Unit;


use \Mockery;
use Tests\TestCase;
use App\Http\Controllers\VenueController;

class VenueControllerTest extends TestCase
{

protected $venueRepositoryInterface;

protected $mock;

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

            $this->mock = \Mockery::mock('App\Interfaces\VenueRepositoryInterface');
    }


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


    public function testControllerIndex()
    {

       $this->mock->shouldReceive('find')->once()->andReturn(2);
       $venueController = new VenueController($this->mock);
       $venueController->index();
       $this->assertEquals($this->mock->find(1),2);
    }

}

VenueController.php

  <?php

namespace App\Http\Controllers;

use App\Interfaces\VenueRepositoryInterface;
use Illuminate\Http\Request;

class VenueController extends Controller
{

protected $venueRepository;

    public function __construct(VenueRepositoryInterface $venueRepository)
    {
        $this->venueRepository = $venueRepository;
    }

    public function index()
    {
        $this->venueRepository->find(1);
        return view( 'venue');
    }

}

VenueRepositoryInterface.php

<?php
// app/Repositories/Contracts/VenueRepositoryInterface.php

namespace App\Interfaces;

interface VenueRepositoryInterface
{
    public function find($id);
    public function findBy($att, $column);
}

?>

VenueRepository.php

<?php
// app/Repositories/venueRepository.php
namespace App\Repositories;

use App\Interfaces\VenueRepositoryInterface;
use App\Venue;

class VenueRepository implements VenueRepositoryInterface
{
    protected $venue;

    public function __construct(Venue $venue)
    {
        $this->venue = $venue;
    }

    public function find($id)
    {
        return 2;
    }

    public function findBy($att, $column)
    {
        return $this->venue->where($att, $column);
    }
}
?>

ОБНОВЛЕНИЕ

Я изменил свой тест на основе приведенных ниже комментариев, но теперь он не работает со следующим

Mockery\Exception\InvalidCountException : Method find(<Any Arguments>) from Mockery_0__VenueRepositoryInterface should be called
 exactly 1 times but called 0 times.

Мой тест, который я пытаюсь сделать, это

Учитывая, что я запрашиваю место, когда я посещаю URL-адрес места, вызывается метод поиска, и возвращается 2.

<?php

namespace Tests\Unit;

use \Mockery;
use Tests\TestCase;


class VenueControllerTest extends TestCase
{

protected $venueRepositoryInterface;

protected $mock;

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

    }


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


    public function testControllerIndex()
    {

        $mock = Mockery::mock('VenueRepositoryInterface')->shouldReceive('find')->once()->andReturn(2);
        $this->app->instance('VenueRepositoryInterface',$mock);
        $response = $this->call('GET','venue');
        $this->assertEquals(200, $response->status());
    }

}

**ОБНОВЛЕНИЕ 2**

Теперь я изменил тест, чтобы следовать тому, что было предложено, теперь это работает. Как ни странно, это не будет работать без утверждения равенства в конце.

**public function testControllerIndex()
{
            $venue = new  Venue();
            $mock = Mockery::mock('App\Interfaces\VenueRepositoryInterface');
            $mock->shouldReceive('find')->once()->with(1)->andReturn($venue);
            $this->app->instance('App\Interfaces\VenueRepositoryInterface',$mock);
            $response =  $this->call('GET', 'venue');
            $this->assertEquals($response->getStatusCode(), 200);
    }**

person JaChNo    schedule 29.01.2018    source источник


Ответы (1)


не уверен, что вы хотите проверить.

$this->mock->shouldReceive('find')->once()->andReturn(2);

эта строка утверждает, что функция find() смоделированного объекта VenueRepositoryInterface будет вызываться ровно один раз и переопределяет поведение функции

затем он вызывается дважды,

   $venueController->index();

и

$this->assertEquals($this->mock->find(1),2);

что приводит к провалу теста.

Второе утверждение не нужно, так как вы просто утверждаете результат заранее, чтобы он все равно прошел.

Кроме того, это не очень хороший тест, так как вы тестируете реализацию функции, а не результат функции.

ОБНОВЛЕНИЕ

в соответствии с этим вопросом кажется, что вы не можете связать такое объявление, поэтому вы нужно будет изменить

$mock = Mockery::mock('VenueRepositoryInterface')->shouldReceive('find')->once()->andReturn(2);

to

$mock = Mockery::mock('VenueRepositoryInterface');
$mock->shouldReceive('find')->once()->andReturn(2);
person cwang    schedule 30.01.2018
comment
Я обновил тест, чтобы он был более эффективным в соответствии с вашими комментариями, я включил обновление в основной пост, оно не работает. но я понимаю, что вы сказали о том, что тест не проверяет то, что нужно - person JaChNo; 30.01.2018