我只是想测试我的Laravel应用。在对项目进行编码时,我试图照顾“胖服务,瘦控制器”的原理,因此将每个逻辑(包括DB逻辑)提取到具有接口的服务类,并注入到控制器中。然后,依赖关系由Laravel提供的IoC容器解决。
我的问题是关于在测试控制器时模拟出这些接口依赖性。在我看来,依赖注入似乎从未被测试正确解决,它总是使用由IoC容器注入的实现,而不是伪造的。
控制器方法示例
public function index(ICrudService $crudService)
{
if (!\Auth::check()) {
return redirect()->route('login');
}
$comps = $crudService->GetAllCompetitions();
return view('competitions.index', ['competitions' => $comps]);
}
设置方法
protected function setUp()
{
parent::setUp();
$this->faker = Faker\Factory::create();
// Create the mock objects
$this->user = \Mockery::mock(User::class);
$this->allComps = new Collection();
for ($i=0; $i<10; $i++)
{
$this->allComps->add(new Competition(['comp_id' => ++$i,
'comp_name' => $this->faker->unique()->company,
'comp_date' => "2018-11-07 17:25:41"]));
}
$this->user->shouldReceive('getAuthIdentifier')
->andReturn(1);
$this->competitionFake = \Mockery::mock(Competition::class);
// Resolve every Competition params with this fake
$this->app->instance(Competition::class, $this->competitionFake);
}
测试
public function test_competition_index()
{
// Mock the Crud Service.
$fakeCrud = \Mockery::mock(ICrudService::class);
// Register the fake Crud Service to DI container.
$this->app->instance(ICrudService::class, $fakeCrud);
// Mock GetALllCompetitions method to return the fake collection.
$fakeCrud->shouldReceive('GetAllCompetitions')
->once()
->andReturn
($this->allComps);
// Authenticate the mock user.
$this->be($this->user);
// Send the request to the route, and assert if the view has competitions array.
$this->actingAs($this->user)->get('competitions')->assertStatus(200);
}
CrudServiceProvider
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->bind('App\Services\Interfaces\ICrudService', function () {
return new CommonCrudService();
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return ['App\Services\Interfaces\ICrudService'];
}
行为
由于HTTP响应500而不是200,所以测试失败。调试时,我可以看到控制器仍在使用ServiceProvider提供的CommonCrudService类,而不是伪造的类。 如果我注释掉CrudServiceProvider,则虚假服务将传递到控制器,并返回我指定的集合。当然,我想保留应用程序的容器。
有人经历过这样的事情吗?
非常感谢!