I am trying to setup a simple unit test for one my controller method.
The goals is to test if the a view has an expected value.
/**
* Does the homepage receive all companies when there is no licensekey provided.
*
* #return void
*/
public function testAllCompaniesOnHomepageWithoutLicensekey()
{
$this->call('GET', '/');
$allCompanies = Company::all();
$this->assertViewHas('allCompanies', $allCompanies);
}
In my conosle I get the following error:
Error: Call to undefined method
Tests\Unit\ExampleTest::assertViewHas()
I am not sure if this is no longer availbale in Laravel 5.5?
Anyone knows how I can test my goal?
Are you migrating from an older Laravel version? There have been changes to Laravel's browser testing in Laravel 5.4 https://laravel.com/docs/5.4/upgrade
In Laravel 5.5 you could try:
$response = $this->get('/');
$allCompanies = Company::all();
$response->assertViewHas('allCompanies', $allCompanies);
Related
I am implementing facebook login with socialite laravel but after successful login with facebook when it return me back to callback url i receive an error
laravel version 5.6
Socailite version 3.0
php version 7.2
public function redirectToProvider()
{
return Socialite::driver('facebook')->redirect();
}
/**
* Obtain the user information from facebook.
*
* #return \Illuminate\Http\Response
*/
public function handleProviderCallback()
{
$user = Socialite::driver('facebook')->user();
return $user->token;
}
Erros look like this.
parse_str(): Calling parse_str() without the result argument is deprecated
C:\xampp\htdocs\ecommerce\vendor\laravel\socialite\src\Two\FacebookProvider.php
Routes.php
// FACEBOOK ROUTES
Route::get('login/facebook', 'Auth\LoginController#redirectToProvider');
Route::get('login/facebook/callback', 'Auth\LoginController#handleProviderCallback');
// FACEBOOK ROUTES END HERE
parse_str(): https://www.php.net/manual/en/function.parse-str.php
Using this function without the result parameter is highly DISCOURAGED and DEPRECATED as of PHP 7.2.
Looking at the version history for the FacebookProvider class on Github the error only seems to exist in version 3.0.0, however, there is not mention of parse_str at all in 3.0.4.
To fix your issue you can run:
composer require laravel/socialite:^3.0.4
I'm having odd behaviour in a laravel 5.5 project. I have some feature tests set up and working, and need to test that a specific route will return a 404 if the id passed in doesn't exist. I have explicit model binding set up in the RouteServiceProvider for my Note model
Route::bind('note', function($value){
return Note::where('id', $value)->first() ?? abort(404);
});
This works for my get route test. This test below passes as expected. ($this->headers is just some bits I set in a setUp method that is needed for a lot of the tests)
/** #test */
public function error_received_if_note_does_not_exist()
{
$this->withExceptionHandling();
$response = $this->json('GET', '/api/v1/note/1', [], $this->headers);
$response->assertStatus(404);
}
but this one for the delete route fails ...
/**
* #test
* #expectedException \Illuminate\Database\Eloquent\ModelNotFoundException
*/
public function error_received_if_note_not_found()
{
$this->withExceptionHandling();
$response = $this->json('DELETE', '/api/v1/note/1', [], $this->headers);
$response->assertStatus(404);
}
with message
Failed asserting that exception of type "\Illuminate\Database\Eloquent\ModelNotFoundException" is thrown.
I get that technically the exception is correct, but I want to assert that I get a 404 error code.
Here is the routes/api.php file
Route::apiResource('note', 'NoteController')->only([
'show',
'destroy'
]);
I'm pulling my hair out. Any ideas welcome.
I think Ive figured this out encase anyone else has this problem.
In the delete test, I removed the $this->withExceptionHandling(); line. Which then allows the test to pass.
If I do the same in the get test it fails. So the get test needs it, but the delete test doesn't.
Randomly.
I've previously had Whoops in 5.1 and 5.0; but since 5.2 the implementation I used earlier no longer works.
I have been unable to find a way to implement Whoops 2.0 to Laravel 5.2 as is.
Any suggestions?
Just add this method to your app/Exceptions/Handler.php file, it overrides the existing method that would generate the Symfony error response. If the app is in config mode, it will return the Whoops response. If you're build some sort of API, you might instead want to use the JsonResponseHandler over the PrettyPageHandler which would give you a nice JSON response for exceptions.
/**
* Create a Symfony response for the given exception.
*
* #param \Exception $e
* #return mixed
*/
protected function convertExceptionToResponse(Exception $e)
{
if (config('app.debug')) {
$whoops = new \Whoops\Run;
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
return response()->make(
$whoops->handleException($e),
method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500,
method_exists($e, 'getHeaders') ? $e->getHeaders() : []
);
}
return parent::convertExceptionToResponse($e);
}
Whoops 2.1 was deployed 4 days ago. I just tried with Laravel 5.2 and it worked just fine.
I just followed Matt Stauffer's tutorial.
https://mattstauffer.co/blog/bringing-whoops-back-to-laravel-5
So thanks to Matteo (phpunit in symfony2 - No tests executed) I can now test my functional tests.
Now I got the following error when running phpunit -c app:
You must change the main Request object in the front controller (app.php)
in order to use the `host_with_path` strategy.
so I did change it in the app.php, from:
$request = RequestFactory::createFromGlobals('host_with_path');
to:
$request = Request::createFromGlobals();
I also updated my swiftmailer-bundle from version 2.3 to 5.4.0.
Unfortunately This did not fix my error.
and this is my ../app/config_test.yml
swiftmailer:
disable_delivery: true
Am I missing something here?
I cannot seem to find this error anywhere on the web. Does someone know how I should fix this error?
After some searching I noticed that the app.php wasn't the problem. It was the DefaultControllerTest.php. The error could be fixed by removing the following lines from the DefaultControllerTest:
$crawler = $client->request('GET', '/hello/Fabien');
$this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0);
Due to recent developments our development team decided to stop using Sonata. As a side effect this bug got fixed. So I won't have a solution for this problem.
The problem here is, that the Client object is using neither app.php nor app_dev.php.
The client creates the request internally. So it won't be the request you need.
The only solution I can see is to override the method Symfony\Bundle\FrameworkBundle\Test\WebTestCase::createClient to return your own client. This client is than responsible for creating the actual request object. The following is the current behavior.
namespace Symfony\Component\HttpKernel;
use Symfony\Component\BrowserKit\Client as BaseClient;
class Client extends BaseClient
{
...
/**
* Converts the BrowserKit request to a HttpKernel request.
*
* #param DomRequest $request A DomRequest instance
*
* #return Request A Request instance
*/
protected function filterRequest(DomRequest $request)
{
$httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent());
foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) {
$httpRequest->files->set($key, $value);
}
return $httpRequest;
}
...
}
You have to override method filterRequest to return kind of a request you want.
I am encountering a very strange thing while doing testing with Laravel 4. It looks like a bug but there's probably a logical explanation.
I have replicated the "bug" in a clean Laravel install and here's my code:
My resource controller /app/controllers/TestController.php:
(Created with php artisan controller:make TestController)
class TestController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
return Response::json(array());
}
// The end of the file is unchanged
In my app/routes.php:
Route::get('/', function()
{
return View::make('hello');
});
// Note the composed part of the URL.
// My problem isn't present if I just use `myapi` or `path` as a url
Route::resource('myapi/path', 'TestController');
Added in /app/test/ExampleTest.php:
public function testTest()
{
$res = $this->call('GET', 'myapi/path');
// Until here everything works right
$this->assertEquals(json_decode($res->getContent()), array());
// Now I call the same URL a second time
$res = $this->call('GET', 'myapi/path');
$this->assertEquals(json_decode($res->getContent()), array());
}
Now I run phpunit and here's what I get:
There was 1 error:
1) ExampleTest::testTest
Symfony\Component\HttpKernel\Exception\NotFoundHttpException:
/home/me/Web/laraveltest/bootstrap/compiled.php:5531
/home/me/Web/laraveltest/bootstrap/compiled.php:4848
/home/me/Web/laraveltest/bootstrap/compiled.php:4836
/home/me/Web/laraveltest/bootstrap/compiled.php:4828
/home/me/Web/laraveltest/bootstrap/compiled.php:721
/home/me/Web/laraveltest/bootstrap/compiled.php:702
/home/me/Web/laraveltest/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Client.php:81
/home/me/Web/laraveltest/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php:332
/home/me/Web/laraveltest/vendor/laravel/framework/src/Illuminate/Foundation/Testing/ApplicationTrait.php:51
/home/me/Web/laraveltest/app/tests/ExampleTest.php:25
In my other project I get a slightly different backtrace, but I have the impression that's the same problem: (but I have no idea of why the other is compiled and this one not)
2) UnitModelTest::testOther
Symfony\Component\HttpKernel\Exception\NotFoundHttpException:
/home/me/Web/my-project/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php:148
/home/me/Web/my-project/vendor/laravel/framework/src/Illuminate/Routing/Router.php:1049
/home/me/Web/my-project/vendor/laravel/framework/src/Illuminate/Routing/Router.php:1017
/home/me/Web/my-project/vendor/laravel/framework/src/Illuminate/Routing/Router.php:996
/home/me/Web/my-project/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:775
/home/me/Web/my-project/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:745
/home/me/Web/my-project/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Client.php:81
/home/me/Web/my-project/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php:327
/home/me/Web/my-project/vendor/laravel/framework/src/Illuminate/Foundation/Testing/ApplicationTrait.php:51
/home/me/Web/my-project/app/tests/UnitModelTest.php:32
In both case the line given in the trace for the test file corresponds to the second call of the test.
As I noted in the comments of the routes.php file, if I use a simple url with no slash, the test passes without problem.
I have no problem when I use the api from the browser.
I found many topics related to the NotFoundHttpException on StackOverflow, but none looks like mine. This one is specifically present when testing and only trigger an error at the second call.
So what am I doing wrong here ? Or is it really a bug ?
The problem is that calls made with the same client will use the provided URI relatively. That means what you actually call is:
myapi/path
myapi/myapi/path
You can fix this if you add a preface the urls with a / to make them absolute to the root of the application.
public function testTest()
{
$res = $this->call('GET', '/myapi/path');
// Until here everything works right
$this->assertEquals(json_decode($res->getContent()), array());
// Now I call the same URL a second time
$res = $this->call('GET', '/myapi/path');
$this->assertEquals(json_decode($res->getContent()), array());
}
If you experience other issues like that it often helps to call
$this->refreshApplication();
(This would also create a new client and therefore solve this issue as well)
In my case this error happened because i change public directory name to public_html my solution was put this in the \App\Providers\AppServiceProvider register method.
public function register()
{
// ...
$this->app->bind('path.public', function() {
return base_path('public_html');
});
}