模拟 Laravel 的 Request::segment 方法
这与 this question 有关,但遵循该解决方案并没有解决我的问题.我也意识到 Laravel 自己的文档 声明你不应该模拟 Request
对象,但我不确定如何编写此测试.
This is related to this question, but following that solution did not fix my issue. I also realize that Laravel's own documentation states that you should not mock the Request
object, but I'm not sure how else to go about writing this test.
这是我要测试的代码的外观:
Here's a semblance of the code I want to test:
public function getThirdSegment()
{
return Request::segment(3);
}
这是我目前进行的一项测试:
Here's a test I currently have:
/**
* @test
*/
public function indexReturnsOk()
{
$this->prepareForTests();
$this->call('GET', '/api/v1/courses');
$this->assertResponseOk();
$this->assertResponseStatus(200);
}
这是失败的,因为 Request::segment(3)
在运行 PHPUnit 时返回 null.我首先尝试像这样模拟 Request 对象:
This is failing because Request::segment(3)
is returning null when running PHPUnit. I first tried to mock the Request object like this:
Request::shouldReceive('segment')->andReturn('courses');
但它仍然返回 null.然后我尝试了这个:
But it still returns null. Then I tried this:
$request = m::mock('IlluminateHttpRequest');
$request->shouldReceive('segment')->andReturn('courses');
Input::swap($request);
segment
方法仍然返回 null.有没有办法mock这个方法的返回值?
And the segment
method is still returning null. Is there any way to mock the return value of this method?
更新
此代码在服务提供商的注册方法中,但我认为这不是问题的原因.从浏览器访问该站点可以满足我的预期,但运行 PHPUnit 似乎并没有充实路由或 URL,或者与请求本身有关的任何内容.
This code is within a service provider's register method, but I don't think that's the cause of the issue. Hitting the site from a browser does what I would expect it to do, yet running PHPUnit doesn't seem to flesh out either the route or the URL, or anything having to do with the request itself.
推荐答案
到目前为止,最好的答案是我做错了.服务提供者在控制器加载之前就运行了,当单元测试时,Laravel 的 IlluminateFoundationTestingTestCase
加载应用程序(调用所有服务提供者的 boot
和 register
方法)在执行 setUp
方法期间,在任何单独测试的执行期间可以进行任何调用之前.
Best answer here so far is I was doing it wrong. Service Providers run way before a controller is even loaded, and, when unit testing, Laravel's IlluminateFoundationTestingTestCase
loads the application (calling all service providers' both boot
and register
methods) during execution of the setUp
method, way before any calls can be made out during the execution of any individual test.
我尝试通过向下移动逻辑来找到解决方案,并得到一些工作,类似于:
I tried finding a solution by moving the logic down and got something to work, something along the lines of:
class MyTestClass extends TestCase
{
public function setUp()
{
// No call to parent::setUp()
// From: IlluminateFoundationTestingTestCase
$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');
}
}
但这不可能是对的,至少感觉不是这样.
But that just can't be right, at least it doesn't feel so.
相反,我认为最好不要依赖服务提供者内部的 Request
对象中的任何内容.相反,为什么不在我想要的控制器中注入一个可以做我需要它做的事情的对象呢?不需要服务提供者,我可以轻松地在单元测试中模拟除 Request
之外的任何对象.我应该相信文档.
Instead, I figure it's probably best not to rely on anything in the Request
object from within Service Providers. Instead, why not just inject an object that can do what I need it to do in the controller I want it to? No Service Provider necessary, and I can easily mock any object other than Request
in Unit Tests. I should've believed the docs.
更新
进一步回答我自己的问题,我相信我最初的错误是我在服务提供者中使用了 Request
对象.我认为,回想起来,您可能根本不应该在服务提供者中使用 Request
对象,因为提供者会加载与 laravel 相关的所有内容(包括工匠命令,当然应该没有请求).我的原始代码在浏览器中运行,但如果我尝试运行任何工匠命令,我可能会注意到问题.
Taking this answer to my own question a bit further, I believe my original mistake was that I was utilizing the Request
object within a Service Provider. I think, on retrospection, that you should probably never use the Request
object at all within a service provider, because providers get loaded for everything related to laravel (including artisan commands, which of course should have no request). My original code worked in the browser, but I probably would have noticed issues had I tried to run any artisan commands.
相关文章