Our team has created a Restful API using laravel. We are doing unit testing on the api using PHPUNIT but encountered a problem on testing a POST request.
Here is the code:
public function create_new_account()
{
$account = array (
'accountName'=>$this->fake->word,
'contactName'=>$this->fake->name,
'contactEmail'=>$this->fake->email,
'address'=>$this->fake->sentence
);
$accounts = json_encode($account);
$this->call('POST','accounts',$accounts);
$this->assertResponseOk();
}
This tests if we can create an account using API but I'm always getting an errror
1) ApiServicesTest::create_new_account
ErrorException: Argument 2 passed to Symfony\Component\HttpFoundation\Request::createRequestFromFactory() must be of the type array, string given, called in /var/www/mcx-api/vendor/symfony/http-foundation/Request.php on line 421 and defined
/var/www/mcx-api/vendor/symfony/http-foundation/Request.php:1999
/var/www/mcx-api/vendor/symfony/http-foundation/Request.php:421
/var/www/mcx-api/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php:775
/var/www/mcx-api/tests/ApiServicesTest.php:35
When you test the api using a client like httprequester/postman it is working fine. The api is required to be passed a JSON data so if I passed the array the api is inserting null values. But when I converted the data to json I get the error above. When I tried dd($accounts) here is the output
"{"accountName":"rerum","contactName":"Ms. Mireille Veum Jr.","contactEmail":"Lindgren.Damaris#gmail.com","address":"Vel quidem consectetur nemo excepturi quod."}"
which means data is converted to json format and should be accepted by the api however I don't get what laravel is complaining. Can somebody point me to where I'm doing it wrong? Thank you very much!
Try sending the json as the content.
$this->call('POST', 'accounts', [], [], [], [], $accounts)
Related
Relatively new to Codeception and trying to hook it up to Slim 3.
Setting up a basic test for a POST request like so:
$I->sendPOST('/user', [
'details' => [
'id' => 0,
'package_id' => 0,
'order_id' => 0
]
]);
On the route itself, I am using Slim 3's getParam to get the details that I sent over like so:
$details = $request->getParam('details', []);
Running the test via --debug, I see that the Request has {"details":{"package_id":0,"order_id":0}
However, it seems as if the details from the getParam are returning nothing.
I've tried sending them separately outside of details but to no avail.
At this point, wondering if it's a PSR-7 compatibility issue between the details I send via Codeception's sendPOST and Slim 3's getParam since the getParam method from Slim came with the comments:
* Fetch request parameter value from body or query string (in that order).
*
* Note: This method is not part of the PSR-7 standard.
Any help is appreciated!
I am using the Microsoft Graph and I need to set up a webhook to receive changes to email and calendar events. I was able to get it working with my PHP Laravel application, but now that I am trying to subscribe to notifications, I am running into issues with validating the notificationUrl, which is pointing to a public server of mine.
The script for creating the webhook is returning the following error:
Client error: POST https://graph.microsoft.com/v1.0/subscriptions resulted in a 400 Bad Request response:
{
"error": {
"code": "InvalidRequest",
"message": "Subscription validation request failed. Response must ex (truncated...)
The truncated part I believe is
Subscription validation request failed. Must respond with 200 OK to this request.
Here is my code for creating the subscription:
$data = [
"changeType" => "created",
"notificationUrl" => "https://anatbanielmethod.successengine.net/office365/webhooks/events",
"resource" => "me/events",
"expirationDateTime" => "2018-12-20T18:23:45.9356913Z",
"clientState" => "secret",
];
$result = $graph->createRequest('POST', '/subscriptions')
->attachBody($data)
->execute();
and here is my method for my notificationUrl:
public function events()
{
//if validationToken exists return that to validate notificationUrl
if(isset($_REQUEST['validationToken'])){
return response($_REQUEST['validationToken'], 200)
->header('Content-Type', 'text/plain');
}
//process event normally for those that have already been validated
}
Once again this URL is public and live and I have tested it by using Postman to send it test posts and it is working fine. Also, I added this route to my VerifyCsrfToken middleware to allow a third party post to hit this URL.
Originally I set up a simple single page PHP script to test validating the notificationUrl and that simple script worked fine. It successfully validates Webhooks created that point to it. Here is that one page script code:
<?php
if(isset($_REQUEST['validationToken'])){
echo $_REQUEST['validationToken']; // needed only once when subscribing
} else {
//process like normal not a validation Token request...
}
}
So I would expect that the Laravel endpoint would work like the simple one page PHP script, and it is when I test both URLs in Postman, but the Laravel endpoint is not validating when Office365 attempts to validate it when creating a new webhook.
I have searched all over for help on this and read through all of the Microsoft developer documentation I can find on webhooks and these are some of the more helpful parts of the documentation but I am still not finding an answer to this issue:
https://learn.microsoft.com/en-us/graph/api/subscription-post-subscriptions?view=graph-rest-1.0
https://learn.microsoft.com/en-us/graph/webhooks#notification-endpoint-validation
Any ideas of this?
Thanks Marc! You were correct about the linefeed being the issue, I am still not sure where the line feed is coming from, some how Laravel appears to be adding it. Needless to say I found a solution by adding an "ob_clean();" right before returning the response. Below is my updated notificationUrl method:
public function events()
{
//if validationToken exists return that to validate notificationUrl
if(isset($_REQUEST['validationToken'])){
ob_clean();//this line is cleaning out that previously added linefeed
return response($_REQUEST['validationToken'], 200)
->header('Content-Type', 'text/plain');
}
//process event normally for those that have already been validated
}
It's odd that JakeD's answer requires the use of ob_clean(). here is my webhook controller method in my Laravel 5.7.x app:
use Illuminate\Http\Request;
public function webhook (Request $request) {
if (filled($request->input('validationToken'))) {
return response($request->input('validationToken'))
->header('Content-Type', 'text/plain');
}
// code to process the webhook after validation is complete
}
I don't see an extra linefeed character and the Microsoft Graph API subscription is validated and created.
so I have created a test class in /test directory
in a testExample function, I have store input and output JSON string into a variable.
converted input and output strings to array by using
json_decode(inputstring, true); json_decode(outputstring, true);
I have used following to test this API
$this->json('POST', 'api/v1/tagging', $input, ['Content-Type' => 'application/json'])
->seeJson([
'conversion_specs' => ["post_engagement"],
]);
Where conversion_specs: ["post_engagement"] is one of the section of output json
how could I assert it and it is printing too much data after hitting
./vendor/bin/phpunit command
I think it's going wrong, can anyone help me to check an API with expected value.
I'm new to using API's and am currently trying to use the Trade Me API on a new application I am developing.
Their authorisation guidelines say they use OAuth to authenticate the API calls and that these can either be specified in the query string or the authorization header.
Being fairly new to API calls, I tried using the guzzlehttp/oauth-subscriber but failed miserably when trying to make the call.
So currently I am just trying to append the details to the query string.
The call I am trying to make requires:
oauth_consumer_key
oauth_signature
oauth_signature_method
Where oauth_consumer_key is the consumer key and oauth_signature is the consumer secret.
When I try to visit this URL to test the URL is correct - https://api.tmsandbox.co.nz/v1/Listings/123.json?oauth_consumer_key=XXX&oauth_signature=XXX&oauth_signature_method=PLAINTEXT
I get an error that:
"ErrorDescription":"Invalid PLAINTEXT signature."
I've obviously replaced my keys in the above URL but I can't see what is wrong with the above, it seems to match their documentation.
Can someone either point out what I am doing wrong?
Assuming you're using Guzzle and Laravel, as the comments stated, this would be a very simple example of how to achieve this (just put it in routes.php):
Route::get( '/', function ()
{
$client = new GuzzleHttp\Client( ["base_uri" => "https://api.tmsandbox.co.nz/v1/"] );
$response = $client->request( "GET", "Listings/123.json", ["headers" => ["Authorization" => 'OAuth oauth_consumer_key="YOUR-CONSUMER-KEY", oauth_signature_method="PLAINTEXT", oauth_signature="YOUR-CONSUMER-SECRET&"']] );
return Response::json($response->getBody()->getContents());
} );
I'm trying to use Zend_Soap_Client to communicate with an ASP.net web service. Here's my client call:
$client = new Zend_Soap_Client(null, array(
'location' => 'http://example.com/service.asmx',
'uri' => 'http://example.com/'
));
$user = new UserDetail();
$result = $client->UserDetails($user);
However this always gives me the error:
System.NullReferenceException: Object reference not set to an instance of an object. at Service.UserDetails(UserDetail UserDetail)
some googling revealed that this is quite a common problem. The most common solution seemed to be to pass the parameters as an array, so I tried:
$result = $client->UserDetails(array('UserDetail' => $user));
but this gave the same error. I also tried passing the params as a stdClass object, nesting the array in another with 'params' as the key, and a few other things but the error is always the same.
I have the ASP code for the web service itself, the relevant method is:
public Result UserDetails(UserDetail UserDetail) {
[some stuff]
Hashtable ht = new Hashtable();
ht = UserDetail.GenerateData();
}
the error is caused by the GenerateData() call.
I assume the UserDetails method is getting null instead of my object as the parameter, but I'm not sure how I should be calling the method, or how I can debug this further. The majority of the Zend_Soap_Client examples I've found seem to be using WSDL, which this service is not; not sure if that is relevant. Any help appreciated!
I eventually solved this with:
$userDetails = new UserDetails();
$userDetails->UserDetail = $user;
$client->UserDetails($userDetails);
it seems ASP.net expects (and returns) params to be nested in an object/array with the same name as the method being called.
If you have any possibility to change the asp.net code I'd suggest you try an implementation of the method UserDetails without parameters just to make sure that code isn't broken.
I would then create a consumer-method in asp.net, debug the http-request and see how the userdetail-object is serialized/broken down in array form. Then it's "just" a matter of creating a similar http request from php.