不确定我的嘲讽是否正确


Unsure if I'm using mockery correctly

我第一次遇到了mock/mock,我不确定下面的测试是否真的触及了我的代码,或者只是测试了我所做的mock ?此外,我意识到这段代码并不适合存储库模式,尽管它的名字是这样的。我会努力的。

类:

<?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);
}

这是一个合适的方式来测试我的类吗?或者这是对嘲弄/嘲讽的错误使用?

您不应该测试返回的内容,而应该测试它是否已保存。这意味着,->save()运行了。对->save()的期望是$model->shouldReceive('save')->andReturn($model);。这没有意义,因为代码没有使用->save()的返回值。

在编程中,你通常处理两种类型的方法:命令和查询。查询可以获取一些值,执行一些逻辑并返回一个值。命令可以获取一些值,与外部源(例如数据库)通信,并且不返回任何值。查询应该存根(这意味着,它们不应该期望调用多少,而只期望返回什么),命令应该模拟(这意味着,它们应该只包含调用多少(以及是否调用)的期望)。

->save()方法是一个命令:它与数据库通信。所以它应该被嘲笑。要模拟对象,使用mock的->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);
}

尽管它的名字,mock是一个默认的存根框架。它不会验证方法是否被调用,除非您显式地指定一个期望,如->once()

有关更多信息,请参阅文档:https://github.com/padraic/mockery-docs/blob/master/reference/expectations.rst