SoapUI Pro, validating response using groovy script - soap

I am using SoapUI Pro to test web services used for creating postal despatch shipments.
I am using a groovy script to validate my web service requests. If I am expecting the request to succeed I look for a value of ‘Allocated’ in the ‘status’ field. If I am expecting the request to fail I look for the correct error code and errorDescription in the integration footer.
Sometimes a valid request will have a warning message (e.g. to inform user that field data is too long and has been truncated). I also want to validate these warning messages as well.
I specify the element path that I want to validate in my data source file and then pass it to my groovy script that does the validation.
The groovy script retrieves the value in the element path and assigns it to a variable actualReturn1 using ..
actualReturn1 = holder.getNodeValue(testElementOne);
where testElementOne could be either
//NS1:completedShipmentInfo/NS1:status/status/statusCode/code
OR
//NS1:createShipmentResponse/NS1:integrationFooter/errors/error/errorCode
The first path is valid and correctly assigns the value of this status field to actualReturn1.
But the second path does not appear to be valid and assigns null to actualReturn1.
Below are part of my 2 response files the elements I’m trying to extract data from.
Response with status element that is extracted successfully..
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<NS1:createShipmentResponse xmlns:NS1="http://www.royalmailgroup.com/api/ship/V1">
<NS1:integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2013-12-02T17:06:11</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">1</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>111111113</applicationId>
<transactionId>420642961</transactionId>
</identification>
</NS1:integrationHeader>
<NS1:completedShipmentInfo>
<NS1:status>
<status>
<statusCode>
<code>Allocated</code>
</statusCode>
</status>
Response with errorCode that can not be extracted…
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<NS1:createShipmentResponse xmlns:NS1="http://www.royalmailgroup.com/api/ship/V1">
<NS1:integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2013-12-02T17:06:13</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">1</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>111111113</applicationId>
<transactionId>420642961</transactionId>
</identification>
</NS1:integrationHeader>
<NS1:integrationFooter>
<errors xmlns="http://www.royalmailgroup.com/integration/core/V1">
<error>
<errorCode>E1101</errorCode>
<errorDescription>Name is a required field</errorDescription>
</error>
</errors>
Could someone tell me why this isn't working for the second response? If I have warning messages in a valid response then I'm also not able to extract the value. Is it because this is in the integrationFooter?

Happened to see this now, so adding the answer.
In the 2nd case, it was not working for you because of the namespace issue.
The element, errors is using default namespace and is different from its parent element integrationFooter. And in your xpath, no namespace was referred to element errors and its child elements.
Here is the script that works for 2nd case:
def xml = '''
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<NS1:createShipmentResponse xmlns:NS1="http://www.royalmailgroup.com/api/ship/V1">
<NS1:integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2013-12-02T17:06:13</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">1</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>111111113</applicationId>
<transactionId>420642961</transactionId>
</identification>
</NS1:integrationHeader>
<NS1:integrationFooter>
<errors xmlns="http://www.royalmailgroup.com/integration/core/V1">
<error>
<errorCode>E1101</errorCode>
<errorDescription>Name is a required field</errorDescription>
</error>
</errors>
</NS1:integrationFooter>
</NS1:createShipmentResponse>
</soapenv:Body>
</soapenv:Envelope>'''
def holder = new com.eviware.soapui.support.XmlHolder( xml )
holder.declareNamespace('a','http://www.royalmailgroup.com/api/ship/V1')
holder.declareNamespace('b','http://www.royalmailgroup.com/integration/core/V1' )
def errorCode = holder.getNodeValue( "//a:integrationFooter/b:errors/b:error/b:errorCode" )
assert errorCode == 'E1101'

Related

SOAP request with certain tags without namespace

Would be the following SOAP request valid according to the standard?
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns2:ServiceReq xmlns:ns2="http://www.tibco.com/service" xmlns:ns1="http://www.tibco.com/framework">
<ns1:HeaderIn>
<ns1:countryISO>FR</ns1:countryISO>
<ns1:callerDateTime>2021-11-26T15:50:08.742Z</ns1:callerDateTime>
</ns1:HeaderIn>
<ns2:request>
<entete>
<profile>Default</profile>
</entete>
<input>
<type>W</type>
<codeRegion>X</codeRegion>
</input>
</ns2:request>
</ns2:ServiceReq>
</soapenv:Body>
</soapenv:Envelope>
I am not sure because certain tags don't have a namespace
There are multiple levels of valid here:
Is it a valid SOAP message as per the SOAP standard? Yes. The SOAP envelope and body tags seem valid.
Is it a valid XML format? Yes, it's a well formed XML file.
Are those elements without a namespace prefix valid? Yes. Elements can be in a default namespace or in no namespace at all.
Is the actual content of the body a valid messages? You can only tell if you verify the message you posted against the expected message as defined in the WSDL file of the web service.
All the elements in the body of the SOAP message should belong to specific namespaces, but sometimes a developer forgets to add a namespace annotation on the element, or copy-pastes something from some place else, or whatever, and you end up with weird looking XMLs like that. The service works and the message is correctly parsed, but it just looks funny.

Problem with validation of SOAP request with Zeep (python)

I have problems to get SOAP request through Zeep, I get a (client) validation error... I have also tested with SoapUI and that does NOT give me the same validation error...
The specification below is from the server... Based on that specification, the OrderStatus and SynchStatus are needed to perform the request.
<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/ xmlns:web="WebServiceProvider">
<soapenv:Header/>
<soapenv:Body>
<web:Order_Get>
<!--Optional:-->
<web:orderOptions>
<web:FromDate>?</web:FromDate>
<web:ToDate>?</web:ToDate>
<web:OrderStatus>?</web:OrderStatus>
<web:SynchStatus>?</web:SynchStatus>
<!--Optional:-->
<web:OrderNumber>?</web:OrderNumber>
<web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
<web:PaymentStatus>?</web:PaymentStatus>
</web:orderOptions>
</web:Order_Get>
</soapenv:Body>
</soapenv:Envelope>
However, executing this from the SoapUI without OrderStatus and SynchStatus will give me a list of all the orders for the specified dates:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="WebServiceProvider">
<soapenv:Header/>
<soapenv:Body>
<web:Order_Get>
<web:orderOptions>
<web:FromDate>2021-03-30</web:FromDate>
<web:ToDate>2021-03-31</web:ToDate>
</web:orderOptions>
</web:Order_Get>
</soapenv:Body>
</soapenv:Envelope>
I want to do the same with Zeep (https://github.com/mvantellingen/python-zeep) but the client validation fails...
I initiate the request with the following code:
api_url = 'https://abc.se/Webservice20/v3.0/webservice.asmx?WSDL'
session.auth = HTTPDigestAuth(username, password)
api = Client(api_url, transport=Transport(session=session))
And then I try to execute the following request:
order_options = {
'FromDate': '2021-03-30',
'ToDate': '2021-03-31',
}
orders = api.service.Order_Get(orderOptions=order_options)
This will result in the following error:
zeep.exceptions.ValidationError: Missing element OrderStatus (Order_Get.orderOptions.OrderStatus)
If I add OrderStatus to the request, I will get a validation error saying that SynchStatus is missing. When that has been added as well, the request is sent to the server.
I.e. it seems like the zeep client is more strict with regards to validating the data in the request than what the server is... Is there a way to force the client to skip this validation?
Many thanks in advance!
Searched a bit more and found a workaround in this post: Getting zeep.exceptions.ValidationError: Missing element for method that worked with suds
So the solution in my case looks like this:
from zeep import xsd
...
order_options = {
'FromDate': '2021-03-30',
'ToDate': '2021-03-31',
'OrderStatus': xsd.SkipValue,
'SynchStatus': xsd.SkipValue,
}
response = api.service.Order_Get(orderOptions=order_options)
This will block zeep from doing client side validation of the parameters OrderStatus and SynchStatus.
it seems like the zeep client is more strict with regards to validating the data in the request than what the server is...
Looks like it.
Looking at the request SoapUI generates based on the WSDL, the two fields you mention are mandatory:
<web:orderOptions>
<web:FromDate>?</web:FromDate>
<web:ToDate>?</web:ToDate>
<web:OrderStatus>?</web:OrderStatus>
<web:SynchStatus>?</web:SynchStatus>
<!--Optional:-->
<web:OrderNumber>?</web:OrderNumber>
<web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
<web:PaymentStatus>?</web:PaymentStatus>
</web:orderOptions>
So the error that the zeep client displays is correct. Zeep inspects the WSDL and generates the corresponding code to use the types in the contract. Your WSDL contract says that OrderStatus and SynchStatus are mandatory. The fact that the server doesn't validate them shows a problem: the web service isn't respecting it's own documented contract
The WSDL and the behavior of the web service should be the same. I suggest you contact the web service owners and ask about this behavior. It might be a validation missing on the server and what you get is just some side effect of that, or the behavior is intentional but someone forgot to update the WSDL to say that you can also make the call without those parameters.
Meanwhile, the workaround is very simple. Download the WSDL, change it to make the two fields optional, then feed this changed WSDL to zeep for it to generate the code, instead of using the original WSDL. You should however clarify this with the web service provider. If it's indeed a neglect of someone, this might be spotted at some point and fixed, making your workaround call fail a server validation because of the missing fields.

How to compose SPML v2 'modify' request to delete object attribute

I need to maintain an Active Directory service via SPMLv2 SOAP requests to an Active Roles Server.
I'm trying to do something ostensibly simple: delete the telephoneNumber attribute from an object. I'd never heard of SPML before so I spent some time trying to understand the specification available on the list of OASIS open standards.
I've figured out how to do it if the value is known. For example, the payload below will delete the telephoneNumber attribute if it matches the value '12345', but not any other value.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:oasis:names:tc:SPML:2:0">
<soapenv:Header/>
<soapenv:Body>
<urn:modifyRequest xmlns:spml="urn:oasis:names:tc:SPML:2:0">
<urn:psoID ID="CN=Some User,OU=User,OU=Accounts,DC=someorganisation,DC=org"/>
<urn:modification>
<modification name="telephoneNumber" operation="delete" xmlns="urn:oasis:names:tc:DSML:2:0:core">
<value>12345</value>
</modification>
</urn:modification>
</urn:modifyRequest>
</soapenv:Body>
</soapenv:Envelope>
What I can't figure out is how to do this for an unspecified value, i.e. I don't care what the value is before I delete it, I just want to delete it. I suspect this has something to do with the SelectionType and I just need to use a 'match anything' selector, but I'm having trouble understanding the specification.
Any ideas?
Edit: To add to the confusion, I see we're using the DSMLv2 namespace for the modification. I just pulled this from a sample on the Active Roles SPML service documentation so I don't know how/why it works. The SPML specification does mention DSML but doesn't give any context around its usage as far as I can tell. It could actually be a vendor specific implementation.
Figured out a solution/work-around to this problem.
To delete the attribute without knowing its current value, you can simply include a 'replace' operation to first set some arbitrary value and include it in the same modify request as the 'delete' operation.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:oasis:names:tc:SPML:2:0">
<soapenv:Header/>
<soapenv:Body>
<urn:modifyRequest xmlns:spml="urn:oasis:names:tc:SPML:2:0">
<urn:psoID ID="CN=Some User,OU=User,OU=Accounts,DC=someorganisation,DC=org"/>
<urn:modification>
<modification name="telephoneNumber" operation="replace" xmlns="urn:oasis:names:tc:DSML:2:0:core">
<value>deleteMe</value>
</modification>
<modification name="telephoneNumber" operation="delete" xmlns="urn:oasis:names:tc:DSML:2:0:core">
<value>deleteMe</value>
</modification>
</urn:modification>
</urn:modifyRequest>
</soapenv:Body>
</soapenv:Envelope>

How to get response value from Currency Converter service response through groovy script in SoapUI?

I'm using Currency Converter webservice to practice groovy script in SoapUI Pro.
In that, I have created a property that should get response / output of the Currency Converter service through groovy script.
For that, I tried the following script which gets all the raw response data :(
I need to get the exact result i.e. converted value and assign to the property.
Can anyone provide me the correct groovy script?
Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET/">
<soapenv:Header/>
<soapenv:Body>
<web:ConversionRate>
<web:FromCurrency>USD</web:FromCurrency>
<web:ToCurrency>INR</web:ToCurrency>
</web:ConversionRate>
</soapenv:Body>
</soapenv:Envelope>
Response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ConversionRateResponse xmlns="http://www.webserviceX.NET/">
<ConversionRateResult>60.54</ConversionRateResult>
</ConversionRateResponse>
</soap:Body>
</soap:Envelope>
Thanks
Karunagara Pandi
First you need access to the Response.
def conversionRateResult = context.expand( '${step_name#Response#//*:ConversionRateResult}' )
Then to assign it to a property depends on multiple things: 1) where are you doing it from, and 2) where do you want the property assigned.
To crawl the hierarchy from a script step, you would do something like:
testRunner.testCase.setPropertyValue("property_name", conversionRateResult)
Consider browsing through the documentation and API.

How to deserialize soap response with multiref in .net?

I am making a .net wcf client for java ws. But when I make a request, and response contains fault, it also contains multiRef section. So I get this exception:
Server returned an invalid SOAP Fault.
End element 'Body' from namespace 'http://schemas.xmlsoap.org/soap/envelope expected. Found element 'multiRef' from namespace ''
This is how response from server looks like (taken directly from network):
<soapenv:Envelope>
<soapenv:Header/>
<soapenv:Body>
<soapenv:Fault>...</soapenv:Fault>
<multiRef>...</multiRef>
</soapenv:Body>
</soapenv:Envelope>
Is there any way to configure my wcf client to deserialize that message right ? Or a possibility to get a raw response xml?