I am working on a test suite in SoapUI that contain both REST and SOAP requests.
The scenario begins with a REST request. From the response I need to take the user name value.
The response is the following:
{
"user_name": "Z.ZCLGN",
"first_name": "Tester1",
"user_code": "19225",
"last_name": "QA"
}
I need the "Z.ZCLGN". How do I split the username value so I could transfer it to the next Soap Request? should I use split like I'm trying to do and if so how?
Thats what I have so far in a groovy script:
def responseAsXml = context.expand( '${GetToken#ResponseAsXml#declare namespace ns1=\'https://10.1.9.13/cvbs/oauth2/token\'; //ns1:Response[1]/ns1:user[1]}' )
log.info responseAsXml
def (user_name, first_name, Tester1, user_code, last_name) = responseAsXml.split("")
You don't need Groovy scripting for that.
Use Property Transfer.
http://www.soapui.org/Functional-Testing/transferring-property-values.html
But if you love scripting so much you still want to do it, here you go:
def json = new JsonSlurper().parseText(jsonText)
def userName = json.user_name
// now use userName in some other request by setting a property, for exampl
testRunner.testCase.setPropertyValue( "MyProp", userName )
More help about Json parsing here:
http://mrhaki.blogspot.se/2011/04/groovy-goodness-parse-json-with.html
But I would also recommend reading the tips for SoapUI beginners:
http://www.soapui.org/Getting-Started/10-tips-for-the-soapui-beginner.html
Related
I'm trying to do query using REST API, and ran into the following problem:
Using GET request on the query endpoint exposes the entire query string, which may contain sensitive data such as SSN, phone number, etc...
https://[instance-url].my.salesforce.com/services/data/v48.0/query/?q=SELECT Id FROM Contact WHERE SSN__c = '123456789'
How can I do such a query using rest api securely?
IS there an equivalent request I can make using at least POST request with post body being the query? since that part is encrypted over https.
Thank you for help
You have two options.
Parameterized Search API. This option is available out of the box with POST as the method. The API is a RESTful interface to Salesforce's text-based search engine. Normally, text-based search uses SOSL as the query language. Parameterized Search API skips SOSL and gives you an easier option to work with.
If you POST the following body to /services/data/v48.0/parameterizedSearch
{
"q": "123456789",
"sobjects": [
{
"name": "Contact",
"where": "SSN__c = '123456789'"
}
],
"fields": ["id"]
}
you should see something like this as the response, assuming single record is returned by search (ID is redacted):
{
"searchRecords" : [ {
"attributes" : {
"type" : "Contact",
"url" : "/services/data/v48.0/sobjects/Contact/003..."
},
"Id" : "003..."
} ]
}
The value of q key in the JSON payload must be the same as the value in the where key/clause. You're doing a full-text search on 123456789 across all objects and all fields in the search index. This could return many records..but you're filtering the search down in a structured way to guarantee that you'll only see Contact records where SSN__c = '123456789'. As long as the objects + fields you're trying to retrieve are present in the index the results you'll see via Parameterized Search in this specific example are going to be the same as that of a SOQL query via /query
Custom REST API (aka Apex REST / Apex web service). This is a typical implementation option for cases like yours. You can send whatever payload via POST and then process it however you like.
Apex class:
#RestResource(urlMapping='/findcontactbyssn')
global class ContactResource {
#HttpPost
global static void findContactBySSN() {
SearchRequest input = (SearchRequest)JSON.deserialize(RestContext.request.requestBody.toString(),SearchRequest.class);
Contact c = [SELECT Id FROM Contact WHERE SSN__c = :input.ssn];
SearchResponse output = new SearchResponse();
output.id = c.id;
RestContext.response.responseBody = Blob.valueOf(JSON.serialize(output));
RestContext.response.statusCode = 200;
}
class SearchRequest {
public String ssn {get;set;}
}
class SearchResponse {
public String id {get;set;}
}
}
POST to /services/apexrest/findcontactbyssn with
{
"ssn": "12345678"
}
and you should see this response:
{
"id": "003..."
}
AFAIK, salesforce only provides a GET method for executing SOQL queries. One can write their own REST endpoint in their org that accepts a query in body and execute it, but thats a waste of time in my opinion.
Query string parameters are secured over https. Its a common misconception, where people think whole url is open in plain text in transmission. When a request is made to an https url, first it establishes a Secure Tunnel to [instance-url].my.salesforce.com then transmits the rest of the url and any other data over the secure tunnel.
If you're worried about some man in the middle attack sniffing out the SSN from your query string, don't. One downside is, if you are accessing this url from a browser instead of a programmatic call, then there is a chance for browser to stored/cache for history or auto complete, then it won't be so good.
But I doubt if you would be able to do this via browser, as salesforce requires a bearer token set in Authorization header and there is no easy way that I know of to set headers while typing the url in the browser or clicking a link.
To know more about how query string is secure over https please refer to this stackoverflow question
I have groovy spript in test step, and MockOperation in MockService.
How to get last request in script?
Now I can check only time of last mock request:
def project = testRunner.testCase.testSuite.project
def mock = testRunner.testCase.testSuite.project.mockServices["mock"]
def service = mock.getMockOperationByName("service")
def req = service.getLastMockResult()
Welcome to Stackoverflow.
For a specific response, you really need to clarify a few things.
In your description, you describe you want "last request". In your code, you do "getLastMockResult". Do you want the last request or the last response?
Is it SOAP or REST?
You also make use of "mockIss". Where does that come from? Is just a typo, and really you mean the "mock" from the previous line?
On a more generic note, given this is a SOAP request, and the Groovy Script teststep is situated in the same testcase as the Soap Request teststep, you should be able to do something like this:
def request = context.expand( '${Name of Soap Request teststep#Request#declare namespace soap=\'http://www.w3.org/2003/05/soap-envelope\'; //soap:Envelope[1]}' )
def response = context.expand( '${Name of Soap Request teststep#Response#declare namespace soap=\'http://www.w3.org/2003/05/soap-envelope\'; //soap:Envelope[1]}' )
log.info request
log.info response
I'm newbie to soap and soapui, I'm trying to create a test case in which I will send the same request(XML attachment) many times(about 500), the problem is that each time I need to increment/change a value in the request (the id).
Therefore, I wonder if the is a way to pass this parameter to the attached xml file ? or if there is another ways to do the test case.
Thank you in advance
UPDATE
here is the content of the xml file :
<mod:sendMSG xmlns:mod="http://test.soap/service/model">
<id>${#Project#parameter1}</id>
<date>2016-04-03T04:03:00</date>
<infos>
<firstName>AT </firstName>
<lastName>AT </lastName>
......
</infos>
</mod:sendMSG>
which is included in the soap request, ass shown in the following image :
Test steps:
Groovy Script
SOAP Request (disabled)
I disabled the SOAP Request because it runs once more after the script has already looped the request x times.
Groovy script:
int loops = 500;
for ( iter in 1..loops ) {
//Overwrite the 'parameter1' property at project level
testRunner.testCase.testSuite.project.setPropertyValue("parameter1", iter.toString())
//log.info("iter: " + testRunner.testCase.testSuite.project.getPropertyValue("parameter1"));
// Run the teststep named 'SOAP Request'
def testStep = testRunner.testCase.testSteps['SOAP Request'];
testStep.run( testRunner, context )
}
Now you should be able to run your TestCase. I recommend saving your project before, I had some problems with SoapUI crashing on me when running.
I think I hit an AWS API Gateway scenario that doesn't appear to have a solution.
I am trying to create a json POST endpoint to validate an address against a USPS service.
The ultimate request looks like this:
http://production.shippingapis.com/ShippingAPI.dll?API=Verify&XML=<AddressValidateRequest USERID="SECRET"><Address><Address1>101 Foo Lane</Address1></Address2><City>Somewhereville</City><State>CA</State><Zip5>90210</Zip5><Zip4></Zip4></Address></AddressValidateRequest>
The issue I'm having is I need to set the XML query string parameter based on my passed in method body, e.g.:
{
address: "101 Foo Lane",
city: "Somewhereville",
state: "CA",
zip: "90210"
}
It appears in the Integration Request, I can specify the "Mapped from", but I can't access the method body, only the method.request.{"path", "querystring" | "header"}.{param_name}
Also there doesn't appear for me to construct a param_name value in the Method Request setup from the incoming method body.
The XML to JSON response mapping is working great if I provide a hard coded XML query string, so I'm down to just the request mapping.
You can map the body to request parameter using method.request.body.JSONPath_EXPRESSION but you can't construct the request parameter using a template similar to what can be done for integration request body. All the available mappings are documented here - http://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
I'm trying to use a service of DocuSign API in an abap project. I want to send a document to a specific email so it can be signed. But im getting the following error:
"errorCode": "INVALID_REQUEST_PARAMETER",## "message": "The request contained at least one invalid parameter. Query parameter 'from_date' must be set to a valid DateTime, or 'envelope_ids' or 'transaction_ids' must be specified.
I tried the following:
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = l_url (https://demo.docusign.net/restapi/v2/accounts/XXXXXX')
proxy_host = co_proxy_host
proxy_service = co_proxy_service
IMPORTING
client = lo_http_client
lo_http_client->request->set_method( method = 'POST').
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'Accept'
value = 'application/json'.
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'X-DocuSign-Authentication'
value = get_auth_header( ). (json auth header)
CALL METHOD lo_http_client->request->set_cdata
EXPORTING
data = create_body( ).
This is my body:
CONCATENATE
`{`
`"emailSubject": "DocuSign REST API Quickstart Sample",`
`"emailBlurb": "Shows how to create and send an envelope from a document.",`
`"recipients": {`
`"signers": [{`
`"email": "test#email",`
`"name": "test",`
`"recipientId": "1",`
`"routingOrder": "1"`
`}]`
`},`
`"documents": [{`
`"documentId": "1",`
`"name": "test.pdf",`
`"documentBase64":` `"` l_encoded_doc `"`
`}],`
`"status": "sent"`
`}` INTO re_data.
The api request to get the Baseurl is working fine. (I know the error is quite specific what the problem is, but i cant find any sources on the docusign api documentation that one of the mentioned parameters should be added to the request)
Thank you in regards
The error message seems to indicate that you're Posting to an endpoint that requires certain query string parameters -- but you're not specifying them as expected in the query string. I'd suggest you check the DocuSign API documentation for the operation you are using, to determine what query string parameters it requires, and then ensure that you're including those parameters in your request URL.
If you can't figure this out using the documentation, then I'd suggest that you update your post to clarify exactly what URL (endpoint) you are using for the request, including any querystring parameters you're specifying in the URL. You can put fake values for things like Account ID, of course -- we just need to see the endpoint you are calling, and what qs params you're sending.
To create an envelope, use
https://demo.docusign.net/restapi/v2/accounts/XXXXXX/envelopes
instead of
https://demo.docusign.net/restapi/v2/accounts/XXXXXX
Thank you for all the answers, i found the mistake. Creating the request wasn´t the problem. I was using the wrong "sending"-method -_-.
now its working :)
lo_rest_client->post( EXPORTING io_entity = lo_request_entity ).