Php 单元测试Laravel 5时无法测试重定向

Php 单元测试Laravel 5时无法测试重定向,php,unit-testing,laravel-5,Php,Unit Testing,Laravel 5,以下是我的测试代码: public function testRegistrationFailsIfNameIsEmpty() { $this->flushSession(); $response = $this->call('POST', '/signup', ['fullname' => '']); $this->assertSessionHasErrors('fullname'); // Passes, expected $this-

以下是我的测试代码:

public function testRegistrationFailsIfNameIsEmpty()
{
    $this->flushSession();
    $response = $this->call('POST', '/signup', ['fullname' => '']);
    $this->assertSessionHasErrors('fullname'); // Passes, expected
    $this->assertTrue($response->isRedirection()); // Passes, expected
    $this->assertRedirectedTo('/signup'); // Fails, unexpected.
}
当我调用该方法时,它正在验证输入,如果验证失败,它会将我重定向回
/signup
,以显示验证错误。我已经在浏览器中手动测试过了,它可以正常工作

然而,当我运行上面的单元测试时,最后一个断言失败了,它认为我被重定向到了
/
而不是
/signup

我不知道它为什么这样做。如果我测试是否发生了重定向,测试通过,因为重定向确实发生了,它只是认为重定向是到
/
而不是
/signup

我已经禁用了所有中间件,所以我知道这并不像来宾中间件那样认为我没有登录

编辑:测试结果:

There was 1 failure:

1) RegistrationTest::testRegistrationFailsIfNameIsEmpty
Failed asserting that two strings are equal.

--- Expected
+++ Actual
@@ @@
-'http://localhost/signup'
+'http://localhost'

我建议您在单元测试此单一测试时,使用dd()打印控制器中的响应对象。这将显示重定向的确切位置。单元测试引擎只是解析响应对象,我相信问题出在代码中,而不是单元测试中。

我在测试Laravel应用程序时也遇到过同样的问题。似乎当您在测试中使用$this->调用,然后控制器使用类似于重定向::back()的东西时,重定向被发送到“/”。我相信这是因为您在执行“$this->call”时不在任何页面上,因此应用程序不确定将您重定向到何处,除非您在控制器中明确说明重定向,即重定向(“somePage”)


但是,当执行类似$this->actingAs($user)->visit('somePage')->按('someButton')这样的操作时,当使用Redirect::back()时,会正确地将您发送回预期页面。很可能是因为应用程序知道您从哪个页面启动。

您能检查一下控制器中的重定向功能测试吗 您可以在函数中放入一个骰子,并找出错误所在 这应该是一个方法上的问题。 然后检查它是否实际进入重定向部分,如果验证失败,则使用request()->validate()将返回调用url。当运行单元测试时,没有调用页面,因此您将被定向到主页

如果验证失败,将引发异常并返回正确的错误 响应将自动发送回用户。如果是 传统HTTP请求时,将生成重定向响应

因此,您要么需要测试重定向是否指向主页,要么伪造调用url。不过,您只是测试验证器,而不是测试代码,这实际上并没有添加任何内容:

session()->setPreviousUrl('/calling/url');

编辑: 实际上,当测试期望重定向到带有命名参数的路由时,这可能很有用

编辑Laravel 5.8:

应使用以下命令调用测试:

$this->from('/calling/url')
    ->get('/some/route')
    ->assertRedirect('/somewhere/else');

您必须设置->from(route('RouteName'))以确保正确设置重定向断言,例如,您要测试请求验证失败。例如,它假设将您的用户重定向到以前的url,并显示验证失败的异常和一些消息。比如说,您想要更新客户名称

    // --- making a post request ----
    $name = 'a new name that is too long';
    $route = route('customer.update');

    $response = $this
        ->withSession(['_previous' => ['url' => 'https://google.com']])
        ->call('POST', $route, [
        '_token' => csrf_token(),
        'name' => $name,
    ]);


    // --- unit test assertions ----
    $response->assertStatus(302);
    $response->assertRedirect('https://google.com');

    $message  = __('@lang_file.some error message text here.');
    $expected = [
        'default' => ['' => [$message]]
    ];
    $actual   = session_errors()->getBags();
    $actual   = json_encode($actual);
    $actual   = json_decode($actual, true);
    $this->assertSame($expected, $actual);
返回会话错误的函数:

function session_errors(): ViewErrorBag
{
  $key    = config('session.keys.errors');
  $errors = session()->get($key, app(ViewErrorBag::class));

  return $errors;
 }

你是否有可能调试你的代码,否则我建议安装这样的环境,它会有用很多次。你如何在浏览器中测试POST方法?你确定你没有测试GET吗?我确定了,位置肯定指向根,因此测试明显按照预期工作,但现在的问题是,为什么重定向会在测试环境中返回到主位置,而在浏览器(本地)中它会返回到它应该返回的位置。我在浏览器中检查了请求流量,没有中间重定向home然后返回/注册,所以我不确定它为什么会这样。此外,没有错误日志表明正在抛出500,并且由于某种原因重定向回主页。在返回之前,在控制器中添加重定向响应时,重定向响应是什么样子的?它应该显示targetUrl和状态代码,告诉您重定向到哪里。这有助于你了解从哪里开始寻找哪里出了问题。在这个建议之前,我使用的是带session的
->([''u previous'=>['url'=>'https://google.com“]])