模拟Laravel的Request :: segment方法 [英] Mocking Laravel's Request::segment method

查看:660
本文介绍了模拟Laravel的Request :: segment方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这与此问题有关,但遵循该解决方案并没有解决我的问题.我还意识到 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('Illuminate\Http\Request');
$request->shouldReceive('segment')->andReturn('courses');
Input::swap($request);

segment方法仍然返回null.有什么方法可以模拟此方法的返回值?

And the segment method is still returning null. Is there any way to mock the return value of this method?

更新

此代码在服务提供商的register方法中,但是我认为这不是问题的根源.从浏览器中访问网站可以达到我的期望,但是运行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的Illuminate\Foundation\Testing\TestCase在执行setUp方法期间会加载应用程序(同时调用所有服务提供者的bootregister方法),在执行任何单独的测试期间可以发出任何呼叫之前.

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 Illuminate\Foundation\Testing\TestCase 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: 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');
    }
}

但是那是不对的,至少感觉不对.

But that just can't be right, at least it doesn't feel so.

相反,我认为最好不要依赖Service Providers中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.

这篇关于模拟Laravel的Request :: segment方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆