Here is my test code:
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.
}
When I call that method, it's validating the input, and if the validation fails, it redirects me back to /signup
to show the validation errors. I've manually tested this in the browser, and it works as expected.
However, when I run the above unit test, the last assertion fails, and it thinks I've been redirected to just /
rather than /signup
.
I have no idea why it's doing this. If I test that a redirect happened at all, the test passes because a redirect does happen, it just thinks the redirect is to /
instead of /signup
.
I've disabled all middleware so I know it's not something like guest middleware thinking I'm logged in when I'm not.
EDIT: Test Results:
There was 1 failure:
1) RegistrationTest::testRegistrationFailsIfNameIsEmpty
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'http://localhost/signup'
+'http://localhost'
Using request()->validate() will return you to the calling url if validation fails. When running unit tests, there is no calling page so you will be directed to home.
https://laravel.com/docs/5.5/validation#quick-writing-the-validation-logic
if validation fails, an exception will be thrown and the proper error response will automatically be sent back to the user. In the case of a traditional HTTP request, a redirect response will be generated
So you either need to test that your redirect is to home, or fudge the calling url. Though then you're just testing the validator rather than your code, which doesn't really add anything:
session()->setPreviousUrl('/calling/url');
https://www.neontsunami.com/posts/testing-the-redirect-url-in-laravel
Edit: Actually, this can be useful when the test expects the redirect to go to a route with a named parameter.
Edit for Laravel 5.8:
The test should be called with:
$this->from('/calling/url')
->get('/some/route')
->assertRedirect('/somewhere/else');
I had this same issue when testing a Laravel app. It seems that when you use $this->call in the test and then your controller uses something like Redirect::back(), the redirect is sent to '/'. I believe this is because you weren't on any page when you made "$this->call" so the application is unsure where to redirect you, unless you are explicit about the redirect in the controller, i.e. redirect('somePage').
However when doing something like $this->actingAs($user)->visit('somePage')->press('someButton'), you are correctly sent back to the expected page when using Redirect::back(). Likely because the app knows what page you started on.
You have to set ->from(route('RouteName')) in order to make sure the redirection assertion is properly set
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With