我正在尝试为我的控制器编写一些单元测试。
我已经实现了一个接口和存储库,它通过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.
最终我想检查当控制器上调用索引方法时,然后它与接口正确交互,因此希望模拟它。我将编写进一步的测试来实际测试接口实现。
VenueControllerTest
<?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.
我正在尝试的测试是
鉴于我要求场地 当我访问场地网址时 然后调用find方法 并且返回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);
}**
答案 0 :(得分:0)
不确定要测试的是什么。
$this->mock->shouldReceive('find')->once()->andReturn(2);
此行声明模拟的VenueRepositoryInterface
对象的find()
函数将被调用一次,并覆盖函数的行为
然后两次调用,
$venueController->index();
和
$this->assertEquals($this->mock->find(1),2);
导致测试失败。
第二个断言是不必要的,因为你只是提前断言结果,所以无论如何它都会通过。
此外,这不是一个好的测试,因为您正在测试函数的实现而不是函数的结果
<强>更新强>
根据this question,似乎你不能像这样链接声明,所以你需要改变
$mock = Mockery::mock('VenueRepositoryInterface')->shouldReceive('find')->once()->andReturn(2);
到
$mock = Mockery::mock('VenueRepositoryInterface');
$mock->shouldReceive('find')->once()->andReturn(2);