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

时间:2015-04-13 20:43:23

标签: php unit-testing laravel-5

这是我的测试代码:

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'

6 个答案:

答案 0 :(得分:6)

如果验证失败,使用request() - > validate()将返回调用URL。运行单元测试时,没有调用页面,因此您将被引导回家。

https://laravel.com/docs/5.5/validation#quick-writing-the-validation-logic

  

如果验证失败,将抛出异常并出现正确的错误   响应将自动发送回用户。在一个案例中   传统的HTTP请求,将生成重定向响应

因此,您需要测试您的重定向是回家,还是捏造调用网址。虽然那时你只是测试验证器而不是你的代码,但它并没有真正添加任何东西:

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

https://www.neontsunami.com/posts/testing-the-redirect-url-in-laravel

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

编辑Laravel 5.8:

应该通过以下方式调用测试:

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

答案 1 :(得分:3)

我在测试Laravel应用时遇到了同样的问题。看来当你在测试中使用$ this->调用然后你的控制器使用类似 Redirect :: back()之类的东西时,重定向会发送到'/'。我相信这是因为当你进行“$ this-> call”时你不在任何页面上,所以应用程序不确定在哪里重定向你,除非你明确指出控制器中的重定向,即重定向('somePage' )。

然而,当执行类似$ this-> actsAs($ user) - > visit('somePage') - > press('someButton')时,您在使用重定向时正确地发送回预期页面: :背部()。可能是因为应用程序知道你开始的页面。

答案 2 :(得分:0)

我建议您在对单个测试进行单元测试时,使用dd()从控制器打印Response对象。这将显示精确重定向的位置。单元测试引擎只解析Response对象,我认为问题出在代码而不是单元测试中。

答案 3 :(得分:0)

您可以检查测试点击控制器中的重定向功能吗? 你可以把一个骰子放在功能中,找出错误在哪里 它应该是方法中的问题。 然后检查它实际进入重定向部分

答案 4 :(得分:0)

您必须设置-> from(route('RouteName')),以确保正确设置了重定向断言

答案 5 :(得分:0)

例如,您要测试请求验证失败。例如,它假设您的用户重定向到先前的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;
 }