Не уверен, правильно ли я использую издевательство

Я впервые сталкиваюсь с mocking/Mockery, и я не уверен, касается ли следующий тест моего кода, или это только тест, который я сделал? Кроме того, я понимаю, что этот код не соответствует шаблону репозитория, несмотря на то, что это имя как таковое... Я над этим поработаю.

Класс:

<?php namespace Acme\Cart\Repositories;

class EloquentCartRepository{
    protected $model_name = 'CartModel';
    protected $model;
    public function __construct($model = null)
    {
        $this->model = is_null($model) ? new $this->model_name : $model;
    }

    public function create_visitor_cart($session_id,$type = 'main'){
        return $this->create('visitor',$session_id,$type);
    }
    protected function create($user_type = null,$user_identifier = null,$type = 'main')
    {
        if(is_null($user_identifier)) throw new \Exception('Cannot create create cart, missing user identifier');
        if(is_null($user_type)) throw new \Exception('Cannot create create cart, missing user type');
        if($user_type == 'visitor')
        {
            $this->model->user_session_id = $user_identifier;
        }
        else
        {
            $this->model->user_id = $user_identifier;
        }
        $this->model->type = $type;
        $this->model->save();
        return $this->model;
    }
}

И мой тест:

/** @test */
public function create_visitor_cart_calls_internal()
{
    $model = m::mock('Models\CartModel');
    $model->shouldReceive('user_session_id')->with('sess123');
    $model->shouldReceive('type')->with('main');
    $model->shouldReceive('save')->andReturn($model);

    $repository = new EloquentCartRepository($model);
    $created_model = $repository->create_visitor_cart('sess123','main');
    $this->assertEquals('sess123',$created_model->user_session_id);
    $this->assertEquals('main',$created_model->type);
}

Это правильный способ проверить мой класс? Или это неправильное использование насмешек / насмешек?

1 ответ

Решение

Вместо проверки того, что возвращено, вы должны проверить, что оно сохранено. Это означает, что ->save() это запустить. Ожидание, которое вы установили ->save() является $model->shouldReceive('save')->andReturn($model);, Это не имеет смысла, так как код не использует возвращаемое значение ->save(),

В программировании вы обычно имеете дело с двумя типами методов: Команды и Запросы. Запросы могут получить какое-то значение, выполнить некоторую логику и вернуть значение. Команды могут получать некоторые значения, связываться с внешним источником (например, базой данных) и ничего не возвращать. Запросы должны быть заглушены (это означает, что они не должны делать никаких ожиданий относительно того, как он вызывается, а только относительно того, что он возвращает), а команды должны быть проверены (это означает, что они должны содержать только ожидания относительно того, сколько (и если) этого называется).

->save() Метод это команда: он связывается с базой данных. Так что надо издеваться. Чтобы издеваться над объектом, используйте ->once() метод издевательства. Он устанавливает ожидание, что он должен быть вызван один раз:

/** @test */
public function create_visitor_cart_calls_internal()
{
    $model = m::mock('Models\CartModel');
    $model->shouldReceive('save')->once();

    $repository = new EloquentCartRepository($model);
    $created_model = $repository->create_visitor_cart('sess123','main');
    $this->assertEquals('sess123',$created_model->user_session_id);
    $this->assertEquals('main',$created_model->type);
}

Несмотря на название, по умолчанию Mockery является фреймворком-заглушкой. Он не подтверждает, что метод вызывается, если вы явно не укажете ожидание, подобное ->once()

Для получения дополнительной информации см. Документы: https://github.com/padraic/mockery-docs/blob/master/reference/expectations.rst

Другие вопросы по тегам