Php 嘲弄拉威尔';s请求::段方法
这与有关,但遵循该解决方案并没有解决我的问题。我还意识到,这说明您不应该模拟Php 嘲弄拉威尔';s请求::段方法,php,laravel,mocking,phpunit,Php,Laravel,Mocking,Phpunit,这与有关,但遵循该解决方案并没有解决我的问题。我还意识到,这说明您不应该模拟请求对象,但我不确定如何编写此测试 下面是我要测试的代码的外观: public function getThirdSegment() { return Request::segment(3); } 这是我目前的一个测试: /** * @test */ public function indexReturnsOk() { $this->prepareForTests(); $this-&
请求
对象,但我不确定如何编写此测试
下面是我要测试的代码的外观:
public function getThirdSegment()
{
return Request::segment(3);
}
这是我目前的一个测试:
/**
* @test
*/
public function indexReturnsOk()
{
$this->prepareForTests();
$this->call('GET', '/api/v1/courses');
$this->assertResponseOk();
$this->assertResponseStatus(200);
}
这是失败的,因为运行PHPUnit时,Request::segment(3)
返回null。我首先尝试模拟请求对象,如下所示:
Request::shouldReceive('segment')->andReturn('courses');
class SiteLayoutComposer extends BaseComposer {
function __construct(Request $request) {
$this->request = $request;
}
public function compose($view)
{
$templateName = preg_match('/siteurlexample/', $this->request->getHost()) ? 'site1' : 'site2';
$view->with('siteLayout', "layouts.sites.{$templateName}");
}
}
但它仍然返回null。然后我试了一下:
$request = m::mock('Illuminate\Http\Request');
$request->shouldReceive('segment')->andReturn('courses');
Input::swap($request);
而段
方法仍然返回null。有没有办法模拟这个方法的返回值
更新
这段代码在服务提供商的register方法中,但我认为这不是问题的原因。从浏览器点击该站点可以实现我所期望的功能,但运行PHPUnit似乎并不能充实路由或URL,也不能充实与请求本身有关的任何内容。到目前为止,最好的答案是我做错了。服务提供者甚至在加载控制器之前就开始运行,在单元测试时,Laravel的
Lightning\Foundation\testing\TestCase
在执行setUp
方法期间加载应用程序(调用所有服务提供者的boot
和register
方法),在执行任何单个测试期间发出任何调用之前
我试图通过向下移动逻辑来找到解决方案,并找到了一些可行的方法,大致如下:
class MyTestClass extends TestCase
{
public function setUp()
{
// No call to parent::setUp()
// From: Illuminate\Foundation\Testing\TestCase
$this->app = $this->createApplication();
$this->client = $this->createClient();
// Not this one!
//$this->app->setRequestForConsoleEnvironment();
$this->app->boot();
// ...
}
public function testWhatever()
{
// Calls to this will now actually have a request object
$this->call('GET', '/api/v1/courses');
}
}
但这不可能是对的,至少感觉不是这样
相反,我认为最好不要依赖服务提供商内部的请求
对象中的任何内容。相反,为什么不在我想要的控制器中注入一个可以完成我需要它做的事情的对象呢?不需要服务提供商,我可以在单元测试中轻松模拟除请求
之外的任何对象。我应该相信那些医生
更新
进一步回答我自己的问题,我认为我最初的错误是我在服务提供商内部使用了
请求对象。回顾一下,我认为您可能根本不应该在服务提供者中使用Request
对象,因为提供者会加载与laravel相关的所有内容(包括artisan命令,当然不应该有请求)。我的原始代码在浏览器中工作,但如果我尝试运行artisan命令,我可能会注意到问题。我在寻找处理使用请求的视图生成器的好方法时遇到了这个问题,最终使用构造函数注入-因为Laravel使用Symfonyrequest
类,使用request::create(request::create”)来“模拟”请求非常容易http://myurl.com)
,并将其传递到类的实例中进行测试。比尝试在请求类上使用存根方法要好得多,而且不依赖于构建整个Laravel应用程序
为清晰起见,视图生成器通常如下所示:
Request::shouldReceive('segment')->andReturn('courses');
class SiteLayoutComposer extends BaseComposer {
function __construct(Request $request) {
$this->request = $request;
}
public function compose($view)
{
$templateName = preg_match('/siteurlexample/', $this->request->getHost()) ? 'site1' : 'site2';
$view->with('siteLayout', "layouts.sites.{$templateName}");
}
}
以及测试:
class SiteLayoutComposerTest extends TestCase {
public function testWillSetTheSiteLayoutToSite1()
{
$request = Request::create('http://www.siteurlexample.com');
$view = View::make('home');
$composer = new SiteLayoutComposer($request);
$composer->compose($view);
$this->assertEquals('layouts.sites.site1', $view->siteLayout);
}
}
不应该是Input::swap($request)
吗request::swap($request)
?谢谢@zwacky,刚刚尝试了这个方法,没有骰子。将自定义对象作为依赖项添加到我测试的类中,而不是请求实例就成功了。