Data Not Found Hit API of Unit Testing Laravel 8.x - unit-testing

I'm new to working on backend to make a unit testing of index method with Bearer Token for authentication.
But, I got failure after I run the command : .\vendor\bin\phpunit like below :
PHPUnit 9.5.27 by Sebastian Bergmann and contributors.
..F 3 / 3 (100%)
Time: 00:00.228, Memory: 24.00 MB
There was 1 failure:
1) Tests\Feature\UserControllerTest::test_returns_user_data_list_successfully
Expected response status code [200] but received 404.
The following errors occurred during the request:
{
"success": false,
"message": "Failed",
"error_code": 4041,
"errors": {
"message": "Data not found"
}
}
Failed asserting that 200 is identical to 404.
C:\Users\artha\Documents\Switch\vendor\laravel\framework\src\Illuminate\Testing\TestResponse.php:177
C:\Users\artha\Documents\Switch\tests\Feature\UserControllerTest.php:18
For UserContoller.php :
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth.jwt');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$user = User::orderBy('created_at', 'DESC')->all();
$message = 'Success';
return $this->sendResponse($user->makeVisible('role'), $message, 200);
}
}
The code of route/api.php :
Route::resource('user', UserController::class, ['except' => ['create', 'edit']]);
And I made UserContollerTest.php like below :
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class UserControllerTest extends TestCase
{
public function test_returns_user_data_list_successfully()
{
$token = 'eyJ0eXA.....dY3CtVO1T4o--8nM';
$response = $this->withHeaders(['Authorization' => 'Bearer '. $token,
'Accept' => 'application/json'])
->get('api/user/index');
$response->assertStatus(200);
}
}
I tried to solved with various ways on internet like read all official documentations and others but I didn't get insight right to solve this. I made .env.testing, too.
Any idea, how to solving this problem?
Thank you for your insight.
I tried to solve with these link :
https://stackoverflow.com/questions/46769959/laravel-phpunit-test-with-api-token-authentication
https://stackoverflow.com/questions/55568924/how-to-pass-bearer-token-to-test-api-using-phpunit-and-liip
https://laravel.com/docs/6.x/http-tests#session-and-authentication

Related

How can I properly get the errors in unit testing laravel as well as disable csrf checks?

I'm trying to test my post method in the controller. The method definition is something like :
public function store(Request $request)
{
$article = new Article;
$article->id = $request->input('article_id');
$article->title = $request->input('title');
$article->body = $request->input('body');
return response(["success"], 200);
}
I've created a test which just stores the data and checks if the response is 200.
Please also show me how can I make this test better new to testing. But I'm getting 404 error I don't know what is the error. How can I display the errors what are the setting I need to configure?
Test:
public function test_post_new_article(){
$article = factory(Article::class)->make();
$this->call('POST', 'article', [
'_token' => csrf_token(),
'article_id' => 6,
'title'=>"hey",
'body' => "this is a body"
])->assertStatus(200);
}
phpunit error:
There was 1 failure:
1) Tests\Unit\ExampleTest::test_post_new_article
Expected status code 200 but received 404.
Failed asserting that false is true.
I'm assuming you defined the route in routes/api.php such that the prefix of your particular route is /api/.
You have to call the full path to the API route:
$this->call('POST', '/api/article', [
'_token' => csrf_token(),
'article_id' => 6,
'title'=>"hey",
'body' => "this is a body"
])->assertStatus(200);
Also, since CSRF should be implemented in your Middleware layer, and it's tedious and silly to add _token to all your test requests, you should probably just disable middleware in your tests:
use Illuminate\Foundation\Testing\WithoutMiddleware;
class MyControllerTest {
use WithoutMiddleware;
... public function testmyUnitTest() { ... }
}

SpringBootTest - Test exception when request is invalid

I developed an API using web-flux which is working fine when I make request using POSTMAN. My code is:
Controller:
#PostMapping("/post", produces = ["application/xml"])
fun post(#Valid request: RequestData): Mono<Response> {
return Mono.just(request)
...
...
...
}
dto:
data class RequestData(
#get:NotBlank
#get:Email
val email: String = "",
)
So whenever I pass invalid email via POSTMAN, I'm catching the exception like below and its working:
#ExceptionHandler
fun bindingExceptionHandler(e: WebExchangeBindException) = "Custom Error Message"
But now when I write UT(#WebFluxTest) for this case (Invalid emaid), It failed.
#Test
fun testWhenInvalidEmail() {
// Request body
val email = "invalidemail"
val request = LinkedMultiValueMap<String, String>()
request.add("email", email)
webTestClient.post().uri("/post")
.body(BodyInserters.fromFormData(request))
.exchange()
.expectStatus().isOk
}
When I debug this, I found that my exceptionHandler not coming into picture when request coming through unit test. I'm using application/x-www-form-urlencoded content type in POST request.
Please let me know where I'm doing wrong.
I followed this question as well but didn't work.
As mentioned on another related question, this has been fixed in Spring Boot 2.1.0.
Also, you shouldn't have to build WebTestClient yourself but instead inject it in your test class (see reference documentation about that):
#RunWith(SpringRunner.class)
#WebFluxTest(MyValidationController.class)
public class MyValidationControllerTests {
#Autowired
private WebTestClient webClient;
#Test
public void testWhenInvalidEmail() {
//...
}
}

Laravel 5.5 socialite not working

I recently tried to integrate laravel socialite with laravel 5.5 but i was getting an error :
GuzzleHttp \ Exception \ ClientException (400) Client error: GET
https://graph.facebook.com/v2.10/me?
access_token=$my_token&appsecret_proof=my_proofsecret resulted in a
400 Bad Request response: {"error":{"message":"Error validating
access token: Session has expired on Tuesday, 03-Oct-17 05:00:00
PDT. The current (truncated...)
Now i have debugged it to some extent and basically this is the line creating the error in FacebookProvider.php line number 89:
protected function getUserByToken($token)
{
$meUrl = $this->graphUrl.'/'.$this->version.'/me?access_token='.$token.'&fields='.implode(',', $this->fields);
if (! empty($this->clientSecret)) {
$appSecretProof = hash_hmac('sha256', $token, $this->clientSecret);
$meUrl .= '&appsecret_proof='.$appSecretProof;
}
$response = $this->getHttpClient()->get($meUrl, [
'headers' => [
'Accept' => 'application/json',
],
]);
return json_decode($response->getBody(), true);
}
this is the line :
$appSecretProof = hash_hmac('sha256', $token, $this->clientSecret);
If i comment it out this whole if else block it seems to work fine, cant figure out whats wrong.
I was actually not selecting the access_token's for my application while getting it from the graph API. I selected the default graph api token. Facebook actually lets you generate access token specific to your App so you have to selection it specifically.. Here is a screenshot of it.
$meUrl .= '&appsecret_proof='.$appSecretProof;
please remove this line and & sign

Assert 403 Access Denied http status with PHPUnit test case

I have a custom error templates in my projects for 404, 403 and other exceptions. I want to create unit test case to assert http errors. When I am logging with user and accessing authorized page of Vendor I am getting 403 Access denied in browser but in Unit test case I am always getting 404 page not found error.
Here is my test scenario:
class ErrorExceptionTest extends WebTestCase
{
public function testAccessDeniedException()
{
$server['HTTP_HOST'] = 'http://www.test.com/';
$client = static::createClient(array('debug' => false), $server);
$client->disableReboot();
$session = $client->getContainer()->get('session');
$firewall = 'main';
$token = new UsernamePasswordToken('user', null, $firewall, array('ROLE_USER'));
$session->set("_security_$firewall", serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$client->getCookieJar()->set($cookie);
$client->request('GET', '/vendor/profile/edit');
$this->assertEquals(403, $client->getResponse()->getStatusCode());
$this->assertContains('Sorry! Access Denied', $client->getResponse()->getContent());
}
}
My test case is being failed, when I print response content it will show 404 error template.
Worked around it and find the issue. So, my solution is no need to use http host.
public function testAccessDeniedException()
{
$client = static::createClient(array('debug' => false));
$session = $client->getContainer()->get('session');
$firewall = 'main';
$token = new UsernamePasswordToken('user', null, $firewall, array('ROLE_USER'));
$session->set("_security_$firewall", serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$client->getCookieJar()->set($cookie);
$client->request('GET', 'fr/vendor/profile/edit');
$this->assertEquals(403, $client->getResponse()->getStatusCode());
$this->assertContains('Sorry! Access Denied', $client->getResponse()->getContent());
}

How to I unit test a #future method that uses a callout?

I have a trigger that fires when an opportunity is updated, as part of that I need to call our API with some detail from the opportunity.
As per many suggestions on the web I've created a class that contains a #future method to make the callout.
I'm trying to catch an exception that gets thrown in the #future method, but the test method isn't seeing it.
The class under test looks like this:
public with sharing class WDAPIInterface {
public WDAPIInterface() {
}
#future(callout=true) public static void send(String endpoint, String method, String body) {
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod(method);
req.setBody(body);
Http http = new Http();
HttpResponse response = http.send(req);
if(response.getStatusCode() != 201) {
System.debug('Unexpected response from web service, expecte response status status 201 but got ' + response.getStatusCode());
throw new WDAPIException('Unexpected response from web service, expecte response status status 201 but got ' + response.getStatusCode());
}
}
}
here's the unit test:
#isTest static void test_exception_is_thrown_on_unexpected_response() {
try {
WDHttpCalloutMock mockResponse = new WDHttpCalloutMock(500, 'Complete', '', null);
WDAPIInterface.send('https://example.com', 'POST', '{}');
} catch (WDAPIException ex) {
return;
}
System.assert(false, 'Expected WDAPIException to be thrown, but it wasnt');
}
Now, I've read that the way to test #future methods is to surround the call with Test.startTest() & Test.endTest(), however when I do that I get another error:
METHOD RESULT
test_exception_is_thrown_on_unexpected_response : Skip
MESSAGE
Methods defined as TestMethod do not support Web service callouts, test skipped
So the question is, how do I unit test a #future method that makes an callout?
The callout is getting skipped because the HttpCalloutMock isn't being used.
I assume that WDHttpCalloutMock implements HttpCalloutMock?
If so, a call to Test.setMock should have it return the mocked response to the callout.
WDHttpCalloutMock mockResponse = new WDHttpCalloutMock(500, 'Complete', '', null);
Test.setMock(HttpCalloutMock.class, mockResponse);
WDAPIInterface.send('https://example.com', 'POST', '{}');
Incidentally, the Salesforce StackExchange site is a great place to ask Salesforce specific questions.