How to access variable declared on Karate mock server or record requests received on mock and somehow send it to main feature file - karate

I have a main feature file which brings up the mock and call an API.
This main API will call other API in the background which goes to my karate mock server. I am able to validate incoming request and send out a response as well.
In this incoming request on mock, I receive a transactionRef, which then appears in the response of my main API.
The flow is something like this
API1 Request
API2 Request (transactionRef) -> API2 Response
API1 Response (transactionRef)
What I want to check is these both are same. Is that possible? I tried setting a variable in mock feature but not able to access it in main feature.
Feature: stateful mock server
Background: Mock
Scenario: pathMatches('/abcd') && bodyPath('/Envelope/Body/infoRequest')!= null
* match karate.typeOf(request) == 'xml'
* xml respInfo = read('classpath:org/xbspro/hos/payloads/infoResponse.xml')
* def tranRef = $request/Envelope/Body/infoRequest/transactionId
* set respInfo/Envelope/Body/infoResponse/transactionId= tranRef
* def response = respInfo
Above is my mock feature. Below is my main feature
* call read('classpath:Abstract.feature')
* xml remResp = response
* match remResponse //transactionId == tranRef

You have 2 options.
You already know how to capture state in the mock by using global variables. Just add a custom end-point which you can call from your API test to get it. Refer: https://stackoverflow.com/a/63512034/143475
Refer to this example where you can use Java to "connect" a mock and the test: https://twitter.com/getkarate/status/1417023536082812935

Related

In karate mocking (karate-netty), how can we override request header value?

Objective:
We want few API calls should go to mock-server(https://192.x.x.x:8001) and others should go to an actual downstream application server(https://dev.api.acme.com).
Setup :
On local, mock server is up with standalone jar on port 8001. e.g https://192.x.x.x:8001
In application config file (config.property)downstream system(which need to mock) defined with mockserver IP i.e https://192.x.x.x:8001
Testing scenario and problem:
1.
Scenario: pathMatches('/profile/v1/users/{id}/user')
* karate.proceed('https://dev.api.acme.com')
* def response = read ('findScope.json')
* def responseStatus = 200ˀˀ
* print 'created response is: ' + response
Now, when we hit API request via postman or feature file then it does karate.proceed properly to https://dev.api.acme.com/profile/v1/users/123/user instead of 192.x.x.x. However, in this request, host is referring to https://192.x.x.x:8001 instead of https://dev.api.acme.com which create a problem for us.
How can we override request header in this case? I did try with karate.set and also with header host=https://192.x.x.x:8001 but no luck.
Thanks!
Please see if the 1.0 version works: https://github.com/intuit/karate/wiki/1.0-upgrade-guide
Unfortunately https proxying may not work as mentioned. If you are depending on this, we may need your help (code contribution) to get this working
If the Host header is still not mutable, that also can be considered a feature request, and here also I'd request you to consider contributing code

Passing a variable from one feature file into another as a part of request URL(not query parameter) in Karate

I have a feature that generates a vehicle id and is stored as a variable in the feature. I want to pass this id as a part of the request URL in another feature as a sort of a teardown activity.
This is how I called it from a feature called activateVehicle.feature
Scenario : Activate a vehicle
* header X-API-Key = apiKey
* def result = callonce read('createVehicle.feature')
* def vehicleId = result.vId
# some workflow steps
........
........
........
# tear down - delete the vehicle created
* call read('deleteVehicle.feature'){ vehcileId: '#(vehicleId)' }
In the called feature - deleteVehicle.feature
Scenario: Delete a vehicle
* header X-API-Key = apiKey
* def myurl = 'https://xxx/vehicle'+ vehicleId +'?permanent=yes'
Given myurl
And request ''
When method delete
Then status 200
Am I right in the approach? I want to reuse deleteVehicle.feature in other workflows as well and hence not doing this operation in the same activateVehicle.feature(which would have been very easy). I referred to the documentation too but it shows how we can use the variables in in the request body but not as a variable that can be used anywhere in the called feature. I don't want to use it in the request body (but want to use it as a part of the request URL) For example:
Scenario:
Given url loginUrlBase
And request { userId: '#(username)', userPass: '#(password)' }
I also referred to How can I call a variable from one feature file to another feature file using Karate API Testing. I followed suit for a solution but am getting a javascript error:
feature.deleteVehicle: -unknown-:11 - javascript evaluation failed:
'https://xxx/vehicle'+ vehicleId +'?permanent=yes', ReferenceError: "vehicleId"
is not defined in <eval> at line number 1
feature.SVT: SVT.feature:80 - javascript evaluation failed: vehicleId: '#(vehicleId)' }, <eval>:1:14 Expected eof
but found }
vehicleId: '#(vehicleId)' }
^ in <eval> at line number 1 at column number 14
Can someone kindly help and advise please?
Can you simplify your example ? The only thing I can make out is you need a space after the call feature and before the call argument:
* call read('deleteVehicle.feature') { vehcileId: '#(vehicleId)' }
The pattern we generally recommend is to setUp not tearDown as tearDown has a risk of not executing if you had an error. That said, please see hooks: https://github.com/intuit/karate#hooks
Sometimes you should just keep it simple and call a feature (with args) only where you need it.

Overriding variable in called feature

I'm using Karate to write integration tests for a REST API. In all test scenarios I have to login users to get an authentification token for all calls related to the REST API. So I want to put the login logic into a separate Karate feature, so I don't have to copy and paste the login API call to all other Scenarios.
From the doku I was able to figure out how to call my login.feature in another feature (logout, with needs a logged in user). I'm also able to pass the username and password to the called login.feature from my calling logout.feature. But I also want my login.feature to be executable on it's own, so I have to define username and password in the login.feature. But if I do so, I'm not able to override this variables from the calling feature.
If I run the logout.feature like follows, the login.feature is not using the email parameter I'm providing in the logout.feature If I delete the email variable from login.feature, it is using the parameter from logout.feature, but then I can't run the login.feature on its own.
Calling logout.feature:
Feature: Login/Logout Test
Background:
* url urlBase http://localhost:5000
* def login = call read('classpath:ires/session/login.feature') {email: "user1#test.com", password: "test"}
* def authToken = login.authToken
Scenario: Testing logout via PUT
Given path '/sessions/logout'
Given param TOKEN = authToken
And request {}
When method PUT
Then status 202
Called login.feature:
Feature: Logs in the given user
Background:
* url urlBase http://localhost:5000
* def email = "user2#test.com"
* def password = "test"
Scenario: Test login via POST
Given path '/sessions/login'
And request {email: '#(email)', password: '#(password)'}
And print email
When method post
Then status 200
And def authToken = response
My suggestion is you can create a login-caller.feature that will call the login.feature with the proper argument passed. Another option is to have email and password defined globally in karate-config.js.
I don't recommend depending on undefined variables as it leads to maintainability problems in the long run, but you can do this kind of conditional check:
* def email = typeof email == 'undefined' ? 'user2#test.com' : email

KARATE - How to get data from response/by running another feature file

I have a feature file that connects to oracle database and gets data and prints in response. Below's the sample piece of code.
dbconnect.feature
def queryDATA = 'QueryData'
When def db = DBConnect.queryDB(host, port, serviceName, username, password, queryDATA)
Then print db
***Note that I have a few more lines of code before this which sets up jdbc and connects to DB with proper credentials
Post this, I need to run real test case which inturn should call dbconnect.feature to get DATA and feed to request. It goes like this;
UserDetails.feature
Background:
* url 'https://soaheader-env-name.com'
* header agent_uid = 'AUTO_TST'
* configure ssl = true
* header Authorization = call read('classpath:ABC/JSFiles/auth.js') {
username: 'XYZ', password: '123' }
* configure logPrettyResponse = true
* configure logPrettyRequest = true
#UserDetails
Scenario Outline: Get User Details
Given path 'somefooterurl/account/<accountno>/user-details-summary'
When method get
Then status 200
Then match response contains 'OK'
I really need to use the data from dbconnect.feature and provide in UserDetails.feature request.
Please suggest a way/ help me with the proper path in karate-github.
A simple example for you,
* def dbCall = call read('dbconnect.feature')
* def db = dbCall.db
please refer karate documentation
Other references if you want to pass values to your feature:
Properly calling an authorization Karate feature with arguments
karate - How to set specific values in a feature file which is called internally

karate | xml post method exeuction

I’m having issue with xml post request where post method is not executed. When I try to post same request body in post man it worked.My test is success with 200 but actual request is not executed.
Please let me know if I’m missing
To pass the request body,I’m calling through java object and payload is correctly constructed and printed.In execution test is success and doesn’t print response.But actually test is not executed.
Only headers are printed.
***************** create-user.feature*****************
Feature: create ims user for provided country
Requires country code,
Background:
# load secrets from json
* def createuser = Java.type('com.user.JavaTestData')
* def create = createuser.createUser("US")
Scenario: get service token
Given url imscreateuserurl
And request create
When method post
Then status 200
* print response
***************** create-user.feature*****************
Here is java class
public class JavaTestData {
private static final Logger logger = LoggerFactory.getLogger(JavaTestData.class);
public static String createUser(String countryCodeInput) {
logger.debug("create user for country code input", countryCodeInput);
Unless you post a full working example, no one can help you. Pretty clear that the value of create is null or empty.
Also I personally think you are wasting your time using Java. The whole point of Karate is to avoid using Java as far as possible.
Look at these examples for ideas: https://github.com/intuit/karate/blob/master/karate-junit4/src/test/java/com/intuit/karate/junit4/xml/xml.feature
Edit: also refer to the doc on type-conversion: https://github.com/intuit/karate#type-conversion
#Peter, here is my feature file
Feature: create ims user for provided country
Requires country code,
Background:
# load secrets from json
* def createuser = Java.type('com.adobe.imscreateuser.JavaTestData')
* def create = createuser.createUser("US")
Scenario: get service token
Given url imscreateuserurl
And header Content-Type = 'application/xml; charset=utf-8'
And request create
When method post
Then status 200
* print response
I have performed print for create and showing complete payload.At when method post -> statement its going as null or empty...
Not sure where it is missing