gpt4 book ai didi

php - 此模拟对象上不存在方法 - Laravel,Mockery

转载 作者:可可西里 更新时间:2023-11-01 00:43:15 27 4
gpt4 key购买 nike

我正在尝试测试一个简单的类。我正在学习本教程 ( http://code.tutsplus.com/tutorials/testing-laravel-controllers--net-31456 )。

我在运行测试时遇到这个错误:

Method Mockery_0_App_Interfaces_MealTypeRepositoryInterface::getValidator() does not exist on this mock object

我正在使用存储库结构。因此,我的 Controller 调用存储库并返回 Eloquent 的响应。

我是 php 和 laravel 的新手。而且我几天前就开始学习测试了,所以对于那些乱七八糟的代码我很抱歉。

我的测试用例:

class MealTypeControllerTest extends TestCase
{
public function setUp()
{
parent::setUp();

$this->mock = Mockery::mock('App\Interfaces\MealTypeRepositoryInterface');
$this->app->instance('App\Interfaces\MealTypeRepositoryInterface' , $this->mock);
}
public function tearDown()
{
Mockery::close();
}

public function testIndex()
{
$this->mock
->shouldReceive('all')
->once()
->andReturn(['mealTypes' => (object)['id' => 1 , 'name' => 'jidlo']]);

$this->call('GET' , 'mealType');

$this->assertViewHas('mealTypes');
}

public function testStoreFails()
{
$input = ['name' => 'x'];

$this->mock
->shouldReceive('getValidator')
->once()
->andReturn(Mockery::mock(['fails' => true]));

$this->mock
->shouldReceive('create')
->once()
->with($input);


$this->call('POST' , 'mealType' , $input ); // this line throws the error

$this->assertRedirectedToRoute('mealType.create');//->withErrors();

$this->assertSessionHasErrors('name');
}

}

我的 EloquentMealTypeRepository:没什么特别有趣的。

class EloquentMealTypeRepository implements MealTypeRepositoryInterface
{
public function all()
{
return MealType::all();
}

public function find($id)
{
return MealType::find($id);
}

public function create($input)
{
return MealType::create($input);
}

public function getValidator($input)
{
return MealType::getValidator($input);
}
}

我 Eloquent 实现:也没什么特别有趣的。

class MealType extends Model
{
private $validator;

/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'meal_types';

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];

/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [];

public function meals()
{
return $this->hasMany('Meal');
}

public static function getValidator($fields)
{
return Validator::make($fields, ['name' => 'required|min:3'] );
}
}

我的 MealTypeRepository 接口(interface):

interface MealTypeRepositoryInterface
{
public function all();

public function find($id);

public function create($input);

public function getValidator($input);
}

最后,我的 Controller :

class MealTypeController extends Controller {
protected $mealType;

public function __construct(MealType $mealType)
{
$this->mealType = $mealType;
}


/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$mealTypes = $this->mealType->all();
return View::make('mealTypes.index')->with('mealTypes' ,$mealTypes);
}

/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$mealType = new MealTypeEloquent;
$action = 'MealTypeController@store';
$method = 'POST';

return View::make('mealTypes.create_edit', compact('mealType' , 'action' , 'method') );
}

/**
* Validator does not work properly in tests.
* Store a newly created resource in storage.
*
* @return Response
*/
public function store(Request $request)
{
$input = ['name' => $request->input('name')];

$mealType = new $this->mealType;

$v = $mealType->getValidator($input);

if( $v->passes() )
{
$this->mealType->create($input);
return Redirect::to('mealType');
}
else
{
$this->errors = $v;
return Redirect::to('mealType/create')->withErrors($v);
}
}

/**
* Display the specified resource.
*
* @param int $id
* @return Response
*/
public function show($id)
{
return View::make('mealTypes.show' , ['mealType' => $this->mealType->find($id)]);
}

/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return Response
*/
public function edit($id)
{
$mealType = $this->mealType->find($id);
$action = 'MealTypeController@update';
$method = 'PATCH';
return View::make('mealTypes.create_edit')->with(compact('mealType' , 'action' , 'method'));
}

/**
* Update the specified resource in storage.
*
* @param int $id
* @return Response
*/
public function update($id)
{
$mealType = $this->mealType->find($id);
$mealType->name = \Input::get('name');
$mealType->save();
return redirect('mealType');
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @return Response
*/
public function destroy($id)
{
$this->mealType->find($id)->delete();
return redirect('mealType');
}

}

这应该就是一切。值得一提的是,该应用程序可以正常工作,只是测试搞砸了。有谁知道,为什么会这样?我看不出 TestCase 方法之间的区别 - testIndex 和 testStoreFails,为什么找到了方法“all”而没有找到“getValidator”。如果有任何建议,我将不胜感激。

最佳答案

也许是旁白,但与通过标题找到此问题的任何人直接相关:

如果:

  1. 您收到错误 BadMethodCallException: Method Mockery_0_MyClass::myMethod() does not exist on this mock object,并且
  2. 您的模拟都没有采用您主题的任何方法,并且
  3. 您的类(class)正在自动加载,(例如使用 composer)

然后在制作模拟对象之前,您需要使用以下代码行强制加载该主题:

spl_autoload_call('MyNamespace\MyClass'); 

然后你可以模拟它:

$mock = \Mockery::mock('MyNamespace\MyClass');

在我的 PHPUnit 测试中,我经常将第一行放入 setUpBeforeClass() 静态函数中,因此它只被调用一次并且与添加/删除的测试隔离开来。所以测试类看起来像这样:

class MyClassTest extends PHPUnit_Framework_TestCase {
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
spl_autoload_call('Jodes\MyClass');
}
public function testIt(){
$mock = \Mockery::mock('Jodes\MyClass');
}
}

我已经忘记这件事三次了,每次都花一两个小时想知道到底是什么问题!

关于php - 此模拟对象上不存在方法 - Laravel,Mockery,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27747000/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com